mm3d-1.3.7/0000777000175000017500000000000011031450307007361 500000000000000mm3d-1.3.7/INSTALL0000644000175000017500000002657410744511356010360 00000000000000Misfit Model 3D Installation ============================ If you are running on Windows see INSTALL.WIN32. If you are running on a Unix-like system, installation instructions follow. Misfit Model 3D requires the following packages for proper operation. They are most likely already installed if you have a modern working Linux system. Qt (3.x or 4.x) with OpenGL support http://www.trolltech.com OpenGL with GLU (probably Mesa if you are using Linux) http://www.mesa3d.org/ For Qt 4.x support, see notes on --with-Qt-dir below. Even if you have these packages installed you may need to install development packages as well. These include header files which are needed to compile Misfit Model 3D. Often such packages are marked as -dev or -devel by your distribution. For example, sometimes Qt is broken up into a qt rpm and qt-devel rpm. In this case, you must have both installed. This program uses autoconf and automake for building from source. What this means is that if you are lucky you can install this program by running these commands at a shell prompt (terminal window): ./configure make su [become root] make install On some system configurations you may need to run "sudo bash" instead of "su" to get a root shell. On Mac OS X, you must run "make mm3d.app" after "make". The default PREFIX (install location) is /usr/local. Files are installed in the following directories. PREFIX/bin - mm3d executable PREFIX/share/mm3d/plugins - plugins PREFIX/share/doc/mm3d - program documentation You can give ./configure arguments to change how the program is compiled. For example you can change the default install location (PREFIX) by specifying --prefix=PATH, where PATH is the new install location. If Qt is not detected and you have it installed, try using --with-Qt-dir to specify the directory where Qt is installed. In a default Qt installation this is what your QTDIR environment variable is set to. Include files are in $QTDIR/include and library files are in $QTDIR/lib. Currently on Unix-like systems you must explicitly use --with-Qt-dir to specify the location of Qt 4.x (ie, Qt 4.x will not be detected automatically). Sometimes development files are in separate paths completely, such as libs in /usr/lib/qt3 and headers in /usr/include/qt3. In this case use --with-Qt-include-dir=/usr/include/qt3 and --with-Qt-lib-dir=/usr/lib/qt3. If you want to link against a specific library of Qt you can use --with-Qt-lib=LIBRARY to specify the library. For example, if you want to force the multi-threaded Qt library, you would use --with-Qt-lib=qt-mt Building with the lua scripting language is now deprecated. Scripting support is not maintained and may be removed in future versions. If you build lua from source, make sure you build and install the shared libraries ("make so" and "make soinstall"). As of Lua 5.0.2 building and installing shared libraries was not default behavior for the Lua build process. See the "Shared Libraries" section in the INSTALL file included in the Lua distribution. Use ./configure --help for a complete list of options. If you need installation help you can contact the misfitmodel3d-help mailing list at: http://www.misfitcode.com/misfitmodel3d/mailinglist.html You can also email "kevin" at the "misfitcode.com" domain. Below are generic instructions for installing programs using autoconf and automake. They are provided for reference if you need more help using ./configure. Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.in' is used to create `configure' by a program called `autoconf'. You only need `configure.in' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not supports the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' can not figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it can not guess the host type, give it the `--host=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name with three fields: CPU-COMPANY-SYSTEM See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are building compiler tools for cross-compiling, you can also use the `--target=TYPE' option to select the type of system they will produce code for and the `--build=TYPE' option to select the type of system on which you are compiling the package. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Operation Controls ================== `configure' recognizes the following options to control how it operates. `--cache-file=FILE' Use and save the results of the tests in FILE instead of `./config.cache'. Set FILE to `/dev/null' to disable caching, for debugging `configure'. `--help' Print a summary of the options to `configure', and exit. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--version' Print the version of Autoconf used to generate the `configure' script, and exit. `configure' also accepts some other, not widely useful, options. mm3d-1.3.7/missing0000755000175000017500000002540610744511356010717 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2005-06-08.21 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). case "$1" in lex|yacc) # Not GNU programs, they don't have --version. ;; tar) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: mm3d-1.3.7/config.h.in0000644000175000017500000000071511025503560011326 00000000000000 /* Define if the X Window System is missing or not being used. */ #undef X_DISPLAY_MISSING #undef CODE_DEBUG #undef HAVE_QT4 #undef PREFIX #undef HAVE_LUA #undef HAVE_LUALIB #undef HAVE_DLOPEN #undef HAVE_XFONT #undef HAVE_GETTIMEOFDAY #undef IS_OSX /* Name of package */ #undef PACKAGE /* Version number of package */ #undef VERSION /* whether byteorder is bigendian */ #undef WORDS_BIGENDIAN /* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ #undef BYTEORDER mm3d-1.3.7/mm3d-win32-installer.nsi0000644000175000017500000001060210750015232013603 00000000000000; Misfit Model 3D - NSI Script (Installer Script) ; ; Copyright (c) 2004-2007 Kevin Worcester ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ; USA. ; ; See the COPYING file for full license text. !define VERSION "1.3.7" !define FILE_VERSION "1_3_7" Name "Misfit Model 3D ${VERSION}" OutFile "mm3d-${FILE_VERSION}-win32-installer.exe" SetCompressor lzma Icon src\pixmap\mm3dlogo-32x32.ico UninstallIcon src\pixmap\mm3dlogo-32x32.ico BrandingText "Misfit Model 3D" CRCCheck on XPStyle on InstallDir "$PROGRAMFILES\Misfit Model 3D" InstallDirRegKey HKCU "Software\Misfit Code\Misfit Model 3D" "INSTDIR" LicenseData COPYING Page license Page components Page directory Page instfiles UninstPage uninstConfirm UninstPage instfiles Section "Misfit Model 3D" SectionIn RO ; Create file type WriteRegStr HKCR "MisfitCode.Mm3dModelFile" "" "MM3D Model File" WriteRegStr HKCR "MisfitCode.Mm3dModelFile\shell\open\command" "" '"$INSTDIR\mm3d.exe" "%1"' WriteRegStr HKCR "MisfitCode.Mm3dModelFile\shell\edit" "" "Edit Model" WriteRegStr HKCR "MisfitCode.Mm3dModelFile\shell\edit\command" "" '"$INSTDIR\mm3d.exe" "%1"' SetOutPath "$INSTDIR" WriteRegStr HKCU "Software\Misfit Code\Misfit Model 3D" "INSTDIR" "$INSTDIR" File COPYING File mm3d.exe File /r /x .svn /x *.htm /x Makefile /x Makefile.* /x *.ts doc imageformats i18n File dll\*.dll WriteUninstaller "Uninstall.exe" SectionEnd Section "Start Menu Shortcuts" ; SetShellVarContext all CreateDirectory "$SMPROGRAMS\Misfit Model 3D" CreateShortcut "$SMPROGRAMS\Misfit Model 3D\Misfit Model 3D.lnk" "$INSTDIR\mm3d.exe" CreateShortcut "$SMPROGRAMS\Misfit Model 3D\Help Documentation.lnk" "$INSTDIR\doc\html\olh_index.html" CreateShortcut "$SMPROGRAMS\Misfit Model 3D\License.lnk" "$INSTDIR\doc\html\olh_license.html" CreateShortcut "$SMPROGRAMS\Misfit Model 3D\MM3D Web Page.lnk" "http://www.misfitcode.com/misfitmodel3d/" CreateShortcut "$SMPROGRAMS\Misfit Model 3D\Uninstall.lnk" "$INSTDIR\Uninstall.exe" SectionEnd SubSection /e "Associate file types" Section "MM3D (Misfit Model 3D)" WriteRegStr HKCR ".mm3d" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "Cal3d" WriteRegStr HKCR ".cal" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "COB (Truespace)" WriteRegStr HKCR ".cob" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "DXF (Autocad DXF)" WriteRegStr HKCR ".dxf" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "LWO (Lightwave)" WriteRegStr HKCR ".lwo" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "MS3D (Milkshape)" WriteRegStr HKCR ".ms3d" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "MD2 (Quake)" WriteRegStr HKCR ".md2" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "MD3 (Quake)" WriteRegStr HKCR ".md3" "" "MisfitCode.Mm3dModelFile" SectionEnd Section /o "OBJ (Alias Wavefront)" WriteRegStr HKCR ".obj" "" "MisfitCode.Mm3dModelFile" SectionEnd SubSectionEnd Section "Uninstall" Delete "$INSTDIR\mm3d.exe" Delete "$INSTDIR\mingw*.dll" Delete "$INSTDIR\qt*.dll" Delete "$INSTDIR\COPYING" Delete "$INSTDIR\Uninstall.exe" RMDir /r /REBOOTOK "$INSTDIR\doc" RMDir /r /REBOOTOK "$INSTDIR\i18n" RMDir /r /REBOOTOK "$INSTDIR\plugins" RMDir /r /REBOOTOK "$INSTDIR\userhome" RMDir /r /REBOOTOK "$INSTDIR\imageformats" RMDir $INSTDIR ; SetShellVarContext all RMDir /r /REBOOTOK "$SMPROGRAMS\Misfit Model 3D" DeleteRegKey HKCR "MisfitCode.Mm3dModelFile" SectionEnd mm3d-1.3.7/Makefile.mingw0000755000175000017500000003055111027625717012102 00000000000000CC=mingw32-gcc CXX=mingw32-g++ WINDRES=windres #DEL=del DEL=rm -f #CXXFLAGS=-Wall -g3 CXXFLAGS=-O1 DEFS=-DMM3D_EDIT -DQT3_SUPPORT -DWIN32 -I.. -I. -I./src -I./src/libmm3d -I./src/mm3dcore -I./src/depui -I./src/qtui -I./src/implui -I./src/commands -I./src/tools -I${QTDIR}/include #DEFS=-DMM3D_EDIT -DQT3_SUPPORT -DCODE_DEBUG -DWIN32 -I.. -I. -I./src -I./src/libmm3d -I${QTDIR}/include -I${QTDIR}/QtCore -I${QTDIR}/QtGui -I${QTDIR}/QtOpenGL -I${QTDIR}/QtNetwork -I${QTDIR}/Qt3Support UIC=${QTDIR}/bin/uic.exe MOC=${QTDIR}/bin/moc.exe LINK=-L${QTDIR}/lib -mwindows -lQtCore4 -lQtGui4 -lQtOpenGL4 -lQtNetwork4 -lopengl32 -lglu32 -lwsock32 #-lpsapi LIB_OBJ= \ src/libmm3d/bsptree.o \ src/libmm3d/cal3dfilter.o \ src/libmm3d/cmdlinemgr.o \ src/libmm3d/cobfilter.o \ src/libmm3d/datadest.o \ src/libmm3d/datasource.o \ src/libmm3d/filedatadest.o \ src/libmm3d/filedatasource.o \ src/libmm3d/memdatadest.o \ src/libmm3d/memdatasource.o \ src/libmm3d/dxffilter.o \ src/libmm3d/filefactory.o \ src/libmm3d/filtermgr.o \ src/libmm3d/glmath.o \ src/libmm3d/log.o \ src/libmm3d/lwofilter.o \ src/libmm3d/md2filter.o \ src/libmm3d/md3filter.o \ src/libmm3d/mesh.o \ src/libmm3d/misc.o \ src/libmm3d/mlocale.o \ src/libmm3d/mm3dfilter.o \ src/libmm3d/mm3dport.o \ src/libmm3d/mm3dreg.o \ src/libmm3d/model.o \ src/libmm3d/model_anim.o \ src/libmm3d/model_bool.o \ src/libmm3d/model_copy.o \ src/libmm3d/model_draw.o \ src/libmm3d/model_group.o \ src/libmm3d/model_influence.o \ src/libmm3d/model_inner.o \ src/libmm3d/model_insert.o \ src/libmm3d/model_meta.o \ src/libmm3d/model_ops.o \ src/libmm3d/model_print.o \ src/libmm3d/model_proj.o \ src/libmm3d/model_select.o \ src/libmm3d/model_texture.o \ src/libmm3d/modelfilter.o \ src/libmm3d/modelstatus.o \ src/libmm3d/modelundo.o \ src/libmm3d/modelutil.o \ src/libmm3d/ms3dfilter.o \ src/libmm3d/msg.o \ src/libmm3d/objfilter.o \ src/libmm3d/pcxtex.o \ src/libmm3d/rawtex.o \ src/libmm3d/texmgr.o \ src/libmm3d/texscale.o \ src/libmm3d/texture.o \ src/libmm3d/tgatex.o \ src/libmm3d/triprim.o \ src/libmm3d/txtfilter.o \ src/libmm3d/undo.o \ src/libmm3d/undomgr.o \ src/libmm3d/weld.o \ MM3D_UI= \ src/qtui/alignwin.base.h \ src/qtui/animconvertwin.base.h \ src/qtui/animexportwin.base.h \ src/qtui/animsetwin.base.h \ src/qtui/animwidget.base.h \ src/qtui/autoassignjointwin.base.h \ src/qtui/backgroundselect.base.h \ src/qtui/backgroundwin.base.h \ src/qtui/boolwin.base.h \ src/qtui/contextgroup.base.h \ src/qtui/contextinfluences.base.h \ src/qtui/contextname.base.h \ src/qtui/contextposition.base.h \ src/qtui/contextprojection.base.h \ src/qtui/contextrotation.base.h \ src/qtui/extrudewin.base.h \ src/qtui/groupwin.base.h \ src/qtui/helpwin.base.h \ src/qtui/jointwin.base.h \ src/qtui/painttexturewin.base.h \ src/qtui/pointwin.base.h \ src/qtui/projectionwin.base.h \ src/qtui/keyvaluewin.base.h \ src/qtui/mapdirection.base.h \ src/qtui/mergewin.base.h \ src/qtui/metawin.base.h \ src/qtui/modelview.base.h \ src/qtui/newanim.base.h \ src/qtui/cal3dprompt.base.h \ src/qtui/ms3dprompt.base.h \ src/qtui/objprompt.base.h \ src/qtui/pluginwin.base.h \ src/qtui/rgbawin.base.h \ src/qtui/statusbar.base.h \ src/qtui/texturecoord.base.h \ src/qtui/textwin.base.h \ src/qtui/texwin.base.h \ src/qtui/transformwin.base.h \ src/qtui/valuewin.base.h \ src/qtui/viewportsettings.base.h MM3D_MOC= \ src/implui/alignwin.moc.cc \ src/implui/aboutwin.moc.cc \ src/implui/animconvertwin.moc.cc \ src/implui/animexportwin.moc.cc \ src/implui/animsetwin.moc.cc \ src/implui/animwidget.moc.cc \ src/implui/animwin.moc.cc \ src/implui/autoassignjointwin.moc.cc \ src/implui/backgroundselect.moc.cc \ src/implui/backgroundwin.moc.cc \ src/implui/boolpanel.moc.cc \ src/implui/boolwin.moc.cc \ src/implui/contextinfluences.moc.cc \ src/implui/contextname.moc.cc \ src/implui/contextpanel.moc.cc \ src/implui/contextposition.moc.cc \ src/implui/contextprojection.moc.cc \ src/implui/contextrotation.moc.cc \ src/tools/cubetoolwidget.moc.cc \ src/tools/cylindertoolwidget.moc.cc \ src/tools/ellipsetoolwidget.moc.cc \ src/depui/errorobj.moc.cc \ src/implui/extrudewin.moc.cc \ src/implui/groupwin.moc.cc \ src/implui/helpwin.moc.cc \ src/implui/jointwin.moc.cc \ src/implui/painttexturewin.moc.cc \ src/implui/pointwin.moc.cc \ src/implui/projectionwin.moc.cc \ src/implui/keyvaluewin.moc.cc \ src/implui/licensewin.moc.cc \ src/implui/mergewin.moc.cc \ src/implui/metawin.moc.cc \ src/implui/mview.moc.cc \ src/depui/modelviewport.moc.cc \ src/implui/newanim.moc.cc \ src/implui/cal3dprompt.moc.cc \ src/implui/ms3dprompt.moc.cc \ src/implui/objprompt.moc.cc \ src/implui/pluginwin.moc.cc \ src/tools/polytoolwidget.moc.cc \ src/tools/projtoolwidget.moc.cc \ src/implui/rgbawin.moc.cc \ src/tools/scaletoolwidget.moc.cc \ src/tools/selectfacetoolwidget.moc.cc \ src/implui/spherifywin.moc.cc \ src/implui/statusbar.moc.cc \ src/depui/textureframe.moc.cc \ src/implui/texturecoord.moc.cc \ src/depui/texwidget.moc.cc \ src/implui/texwin.moc.cc \ src/implui/transformwin.moc.cc \ src/implui/valuewin.moc.cc \ src/implui/viewportsettings.moc.cc \ src/implui/viewpanel.moc.cc \ src/implui/viewwin.moc.cc \ MM3D_MOC_OBJ= \ src/implui/alignwin.moc.o \ src/implui/aboutwin.moc.o \ src/implui/animconvertwin.moc.o \ src/implui/animexportwin.moc.o \ src/implui/animsetwin.moc.o \ src/implui/animwidget.moc.o \ src/implui/animwin.moc.o \ src/implui/autoassignjointwin.moc.o \ src/implui/backgroundselect.moc.o \ src/implui/backgroundwin.moc.o \ src/implui/boolpanel.moc.o \ src/implui/boolwin.moc.o \ src/implui/contextgroup.moc.o \ src/implui/contextinfluences.moc.o \ src/implui/contextname.moc.o \ src/implui/contextpanel.moc.o \ src/implui/contextposition.moc.o \ src/implui/contextprojection.moc.o \ src/implui/contextrotation.moc.o \ src/tools/cubetoolwidget.moc.o \ src/tools/cylindertoolwidget.moc.o \ src/tools/ellipsetoolwidget.moc.o \ src/tools/rotatetoolwidget.moc.o \ src/tools/torustoolwidget.moc.o \ src/tools/toolwidget.moc.o \ src/depui/errorobj.moc.o \ src/implui/extrudewin.moc.o \ src/implui/groupwin.moc.o \ src/implui/helpwin.moc.o \ src/implui/jointwin.moc.o \ src/implui/painttexturewin.moc.o \ src/implui/pointwin.moc.o \ src/implui/projectionwin.moc.o \ src/implui/keyvaluewin.moc.o \ src/implui/licensewin.moc.o \ src/implui/mapdirection.moc.o \ src/implui/mergewin.moc.o \ src/implui/metawin.moc.o \ src/implui/mview.moc.o \ src/depui/modelviewport.moc.o \ src/implui/newanim.moc.o \ src/implui/cal3dprompt.moc.o \ src/implui/ms3dprompt.moc.o \ src/implui/objprompt.moc.o \ src/implui/pluginwin.moc.o \ src/tools/polytoolwidget.moc.o \ src/tools/projtoolwidget.moc.o \ src/implui/rgbawin.moc.o \ src/tools/scaletoolwidget.moc.o \ src/tools/selectfacetoolwidget.moc.o \ src/implui/spherifywin.moc.o \ src/implui/statusbar.moc.o \ src/depui/textureframe.moc.o \ src/implui/texturecoord.moc.o \ src/depui/texwidget.moc.o \ src/implui/texwin.moc.o \ src/implui/transformwin.moc.o \ src/implui/valuewin.moc.o \ src/implui/viewportsettings.moc.o \ src/implui/viewpanel.moc.o \ src/implui/viewwin.moc.o \ MM3D_OBJ= \ src/3dm.o \ src/mm3dcore/3dmprefs.o \ src/implui/aboutwin.o \ src/mm3dcore/align.o \ src/commands/aligncmd.o \ src/implui/alignwin.o \ src/mm3dcore/allocstats.o \ src/implui/animconvertwin.o \ src/implui/animexportwin.o \ src/implui/animsetwin.o \ src/implui/animwidget.o \ src/implui/animwin.o \ src/tools/atrfartool.o \ src/tools/atrneartool.o \ src/commands/backgroundcmd.o \ src/implui/autoassignjointwin.o \ src/implui/backgroundselect.o \ src/implui/backgroundwin.o \ src/implui/boolpanel.o \ src/implui/boolwin.o \ src/implui/contextgroup.o \ src/implui/contextinfluences.o \ src/implui/contextname.o \ src/implui/contextpanel.o \ src/implui/contextposition.o \ src/implui/contextprojection.o \ src/implui/contextrotation.o \ src/mm3dcore/contextwidget.o \ src/mm3dcore/contextpanelobserver.o \ src/tools/bgmovetool.o \ src/tools/bgscaletool.o \ src/mm3dcore/bounding.o \ src/mm3dcore/cmdline.o \ src/mm3dcore/cmdmgr.o \ src/mm3dcore/command.o \ src/commands/capcmd.o \ src/commands/copycmd.o \ src/tools/cubetool.o \ src/tools/cubetoolwidget.o \ src/tools/cylindertool.o \ src/tools/cylindertoolwidget.o \ src/mm3dcore/decal.o \ src/mm3dcore/decalmgr.o \ src/commands/deletecmd.o \ src/commands/dupcmd.o \ src/commands/edgedivcmd.o \ src/commands/edgeturncmd.o \ src/tools/ellipsetool.o \ src/tools/ellipsetoolwidget.o \ src/tools/extrudetool.o \ src/depui/errorobj.o \ src/commands/extrudecmd.o \ src/implui/extrudewin.o \ src/commands/faceoutcmd.o \ src/commands/flattencmd.o \ src/commands/flipcmd.o \ src/implui/groupwin.o \ src/implui/helpwin.o \ src/commands/hidecmd.o \ src/commands/invertcmd.o \ src/commands/invnormalcmd.o \ src/commands/jointcmd.o \ src/commands/pointcmd.o \ src/commands/assignjointcmd.o \ src/tools/jointtool.o \ src/tools/pointtool.o \ src/tools/projtool.o \ src/implui/jointwin.o \ src/implui/painttexturewin.o \ src/implui/pointwin.o \ src/implui/projectionwin.o \ src/implui/keycfg.o \ src/implui/keyvaluewin.o \ src/implui/licensewin.o \ src/mm3dcore/luaif.o \ src/mm3dcore/luascript.o \ src/commands/makefacecmd.o \ src/implui/mapdirection.o \ src/implui/mergewin.o \ src/implui/metawin.o \ src/tools/movetool.o \ src/implui/msgqt.o \ src/implui/mview.o \ src/depui/modelviewport.o \ src/commands/pastecmd.o \ src/mm3dcore/pluginmgr.o \ src/implui/newanim.o \ src/implui/cal3dprompt.o \ src/implui/ms3dprompt.o \ src/implui/objprompt.o \ src/implui/pluginwin.o \ src/tools/polytool.o \ src/tools/polytoolwidget.o \ src/tools/projtoolwidget.o \ src/mm3dcore/prefparse.o \ src/mm3dcore/prefs.o \ src/implui/qtmain.o \ src/implui/qttex.o \ src/tools/rectangletool.o \ src/implui/rgbawin.o \ src/mm3dcore/rotatepoint.o \ src/commands/rotatetexcmd.o \ src/tools/rotatetool.o \ src/tools/scaletool.o \ src/tools/scaletoolwidget.o \ src/tools/selectfacetoolwidget.o \ src/mm3dcore/scriptif.o \ src/tools/selectbonetool.o \ src/tools/selectpointtool.o \ src/tools/selectprojtool.o \ src/tools/selectconnectedtool.o \ src/tools/selectfacetool.o \ src/tools/selectgrouptool.o \ src/tools/selectvertextool.o \ src/tools/sheartool.o \ src/commands/selectfreecmd.o \ src/commands/simplifycmd.o \ src/commands/snapcmd.o \ src/commands/spherifycmd.o \ src/implui/spherifywin.o \ src/implui/statusbar.o \ src/stdcmds.o \ src/stdfilters.o \ src/stdtexfilters.o \ src/stdtools.o \ src/commands/subdividecmd.o \ src/mm3dcore/sysconf.o \ src/depui/textureframe.o \ src/implui/texturecoord.o \ src/mm3dcore/texturetest.o \ src/depui/texwidget.o \ src/implui/texwin.o \ src/implui/transformwin.o \ src/implui/transimp.o \ src/libmm3d/translate.o \ src/mm3dcore/tool.o \ src/mm3dcore/toolbox.o \ src/mm3dcore/toolpoly.o \ src/tools/rotatetoolwidget.o \ src/tools/torustool.o \ src/tools/torustoolwidget.o \ src/tools/toolwidget.o \ src/commands/unweldcmd.o \ src/implui/valuewin.o \ src/tools/vertextool.o \ src/tools/dragvertextool.o \ src/implui/viewportsettings.o \ src/implui/viewpanel.o \ src/implui/viewwin.o \ src/implui/viewwin_influences.o \ src/commands/weldcmd.o .PHONY: all mm3d_ui mm3d_moc mm3d clean all: config mm3d_ui mm3d_moc mm3d config: cmd /c copy config.h.mingw config.h mm3d_ui: ${MM3D_UI} mm3d_moc: ${MM3D_MOC} mm3d: ${MM3D_MOC_OBJ} ${LIB_OBJ} ${MM3D_OBJ} ${WINDRES} src/icon.rc src/icon.o ${CXX} ${CXXFLAGS} ${DEFS} -o mm3d.exe ${MM3D_OBJ} ${MM3D_MOC_OBJ} ${LIB_OBJ} src/icon.o ${LINK} installer: mm3d cp -r ../dll . cp -r ../imageformats . strip mm3d.exe makensis mm3d-win32-installer.nsi %.o : %.cc ${CXX} ${DEFS} -c $< -o $@ ${CXXFLAGS} %.o : %.c ${CC} ${DEFS} -c $< -o $@ ${CXXFLAGS} %.base.h: %.ui ${UIC} $< -o $@ %.moc.cc: %.h ${MOC} $< -o $@ clean: ${DEL} ${LIB_OBJ} ${DEL} ${MM3D_UI} ${DEL} ${MM3D_MOC} ${DEL} ${MM3D_OBJ} ${DEL} ${MM3D_MOC_OBJ} ${DEL} src/*.base.* ${DEL} src/icon.o ${DEL} mm3d.exe mm3d-1.3.7/ChangeLog0000644000175000017500000002410011000471710011041 00000000000000Changes for 1.3.7 Added "Apply to selected" for Transform Model Export Selected (geometry, joints, points, and textures) Set exact position of rotate point for rotate tool More complete version support for Cal3D (700 through 1200) Read compressed animations in Cal3D Report error if saving MD2 or MD3 with faces that are not assigned to a group Fix to dissallow primitives additions using subdivide or addPoint Fix interpolation bug where rotation was not taking the shortest path to the new orientation Have a minimum animation redraw of 20 fps to show interpolation on slow animations Performance fixes for normal calculation (about 40% speed improvement) Performance fixes for MD3 loading (about 8x speed improvement) Added --enable-profile to ./configure Added --language to override the system locale Prevent select connected from selecting hidden faces Do not perform selection in frame animation mode if there are no animations Changed poly tool's "Fan" checkbox into a Strip/Fan combo box Implemented new equiv test and split CompareBits into CompareParts and PartProperties Changes for 1.3.6 Save/restore window size Include projection in frame all/selected command Open projection window from group and projection properties panels Allow multiple multiple bone joints for MS3D (subversions 1 and 2) Initial Cal3D support Better MD3_PATH handling Get MD3_PATH from shaders as well as model header Allow separate MD3_PATH for each shader Corrected capitalization for "Normals Face Out" command Split keyboard shortcut for flip front/back (backslash) view and flip ortho/persp (backtick) Added "Delete" button to animation model panel Redraw animation when loop is enabled/disabled (affects interpolation) Replaced lex/yacc code with custom preferences parser lex/yacc parser was having parse failures on some archs Allow MD2 texture coordinates to go outside of 0.0 to 1.0 range Report error if MD2 has more than one assigned material Remove trailing underscore on MD2 animation names Updated configuration for newer autoconf (2.61) and automake (1.9) Remember last skeletal/frame selection for new animation window Stop playing animation when a new animation is added. Error message when attempting to paste animation frame of wrong type Fixed bug where an influences with a weight of 0 has no influence, rather than placing the influenced object at the origin Fixed interpolation problem with translation keyframes on looped animations Fixed translation of animation name copy/split in animation sets window Fixed initial rotation of points for frame animations Other misc. translation fixes Added ../i18n to search path for translation files Treat unhandled backslashes in preferences as regular backslashes Changed error message on uknown file type to indicate it is probably a file extension problem Add ".mm3d" at save time if filename does not have an extension Use model vertex and point list sizes for writing frame animation data instead of using the size of the lists in the animation frames Added some sanity checking to MM3D loading code Removed several unused modules Added shell script for making source code tags Changes for 1.3.5 Re-organized menus Added "Rotate" tool in texture coordinate window Added "Face Out" command to make triangle normals point outward from enclosed hulls Added File|Export... to save without changing working filename or clearing unsaved flag Restrict Save and Save As to types with more complete support (everything else must use "Export...") Added Copy/Paste selected keyframe (for skeletal and frame) Added toolbar option on proj tool to create specific projection type Write texture coordinates for MM3D even if there are no materials MM3D no longer uses packed structs for mm3d, ms3d, tga, and pcx formats Improved material support for COB export Animation using Quaternion interpolation (prevent strange rotations when rotating on more than one axis) Fixed animation image export Fixed "Clear Animation Frame" for skeletal (broken when anim window was make dockable) Fix (hack) for Perspective label on all viewports Fixes for projection mapping at vertical extremes MD3 fixes: save case-insensitive animation names, cancel load if user selects "cancel" on player model Changes for 1.3.4 Support for internationalization Initial Slovak translation Show tool key accelerators in toolbar tool tip Rename bone joints and points from properties context panel Automatic bone joint assignment Extrude tool Option to create sphere from center Option to create torus from center Bring non-modal dialogs to front on open request when already open Fixes for MD2 (rotate orientation to match MM3D, prevent inversion of left/right, don't require animations to save/load), use MD2_PATH meta data for skin path instead of always assuming player model Fix for empty joint weight boxes Fix for starting in animation mode with animation toolbar hidden Changes for 1.3.3a Compilation fix for 64-bit architectures Changes for 1.3.3 Global transforms (translate, rotate, scale, arbitrary matrix) Disabled Lua by default Plane projection mapping Rotation on center of 3D viewport rather than origin Allow group material change from group properties panel Open group, material window from properties panel Can use orthographic projection from any angle (including tools) Can use Ctrl+Keyboard and Ctrl+ScrollButtons to rotate Rotate on Z axis (Ctrl+Mouse Wheel or Ctrl+Plus/Minus) Rotating fixed orthographic view switches to free orthographic automatically Hot key for saving and restoring viewport (Ctrl+Number to save, Number to restore) Tool to drag vertex on triangle Use tool keyboard shortcuts in texture coord window (Select Vertex, Move, Scale) Made texture coordinate window non-modal Texture coordinate window shows all selected faces (even if they do not belong to the same group) Scale tool in texture coordinate window has options for keeping aspect ratio and scaling from center Use Qt for drawing text in viewport instead of GLXFont (more portable) Fixed crash on alpha blending for non-texture materials Fixed OBJ material file creation on Win32 Fixed render menu selection indicators in Qt4/Win32 Changes for 1.3.2 Added "Influences Menu", all non-animation joint functions moved here Vertices and points can be assigned to multiple weighted bone joints Added "Paint Texture" window that saves a texture with the faces mapped onto it so that it can be painted over with a paint program Sphere and Cylinder mapping (Texture projection) Pan and zoom on texture coordinate edit window Keyboard shortcut customization (text file) Moved rendering options into a submenu of the View menu Added render option to turn off drawing of back-facing polygons Rotate tool rotation point defaults to center of selected objects Can create a new group by selecting "" in the group context panel Vertices can be created individually Made "Snap to Vertex" apply to bone joints, points, and projections Prevent viewport zoom/pan changes while tool is active Fixed MD3 crash on save without animations Fixed MD3 texture paths Fixed texture coordinates in MD2 for non-square skin images Fixed undo/redo selection on polygon tool Standardized enum declarations Standardized struct declarations Re-organized directory structure Corrected a typo in the View Window documentation Purge intermediate status bar messages if queue is too long (error messages not purged) Updated MM3D format documentation to include Points and Frame Anim Points Updated copyright dates Changes for 1.3.1 Added initial MD3 support (Initial filter written by Russell Valentine) Added Boolean operations (Union, Subtraction, Intersection) Added Simplify Mesh command Tint selected faces (uses lighting) User-defined viewport grid settings Allow setting multiple joint rotations at once (experimental) Allow changing/removing a texture on an existing material Added point rotation to properties window Added joint keyframe rotation to properties window Added points to the status bar primitive count Added .TXT model file format Added .RAW texture file format Use entire texture frame for 3D texture preview Do not exit on preferences parse failure Fixed looping animation frame time bug Fixed bolt point rotation and translation on model merge Fix for NaN in Matrix::getRotation() Fixed scoping error for gcc 4.1.1 Added virtual destructor for Model::Observer Changes for 1.3.0 (from 1.2.0-final) Snap to Grid Snap to Vertex Converted animation window to smaller, dockable window Added context-sensitive panel for editing position and group properties (more functionality to come) See View -> Show Properties Edge Turn command Edge Divide command Cap holes command Fixes for ./configure with 64-bit libraries Fixes for 64-bit safe (draw context, and pointer debug output) Initial bolt point support Initial .cob and .dxf support (read/write geometry and materials) Fixed crash on calculateFrameNormals if animation is out of range Append underscore to MD2 animation names that end in numbers to prevent truncation of animation name Change MD2 loading code to remove trailing digits instead of truncating at the first digit Polygon tool creates triangle to face tool viewport Fix for Face select in Frame Animation mode (patch from Russell Valentine) Fix for MD2 GL commands section (terminate with 0) Fixed scaling for co-axial points (division by zero causing undefined coordinates) Removed qpixmap uic hack in the Makefile mm3d-1.3.7/man/0000777000175000017500000000000011031450307010134 500000000000000mm3d-1.3.7/man/Makefile.in0000644000175000017500000002066611025503556012137 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = man DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BYTEORDER = @BYTEORDER@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_PROFILE = @CORE_PROFILE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLOPEN_LIBS = @DLOPEN_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ HAVE_QT4 = @HAVE_QT4@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ LUALIB_CCFLAGS = @LUALIB_CCFLAGS@ LUALIB_DIR = @LUALIB_DIR@ LUALIB_LIBS = @LUALIB_LIBS@ LUA_CCFLAGS = @LUA_CCFLAGS@ LUA_DIR = @LUA_DIR@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PROFILE = @PROFILE@ QGL_LIBS = @QGL_LIBS@ QT_CXXFLAGS = @QT_CXXFLAGS@ QT_DIR = @QT_DIR@ QT_LIBS = @QT_LIBS@ QT_LRELEASE = @QT_LRELEASE@ QT_MOC = @QT_MOC@ QT_UIC = @QT_UIC@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ EXTRA_DIST = \ mm3d.1 all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu man/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu man/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-info-am all: install: $(INSTALL) -d $(DESTDIR)$(datadir)/man/man1/ ${INSTALL} -m 0644 mm3d.1 $(DESTDIR)$(datadir)/man/man1 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mm3d-1.3.7/man/Makefile.am0000644000175000017500000000022010744511356012112 00000000000000EXTRA_DIST = \ mm3d.1 all: install: $(INSTALL) -d $(DESTDIR)$(datadir)/man/man1/ ${INSTALL} -m 0644 mm3d.1 $(DESTDIR)$(datadir)/man/man1 mm3d-1.3.7/man/mm3d.10000644000175000017500000000341410744511356011010 00000000000000.TH MM3D 1 "May 31, 2007" .SH NAME mm3d \- Misfit Model 3D .SH SYNOPSIS .B mm3d .RI [ options ] " files" ... .br .SH DESCRIPTION This manual page documents briefly the .B mm3d command. .PP \fBmm3d\fP is an OpenGL\-based 3D model editor that works with triangle\-based models. It supports multi\-level undo, skeletal animations, simple texturing, scripting, command\-line batch processing, and a plugin system for adding new model and image filters. Complete online help is included. It is designed to be easy to use and easy to extend with plugins and scripts. .SH OPTIONS These programs follow the usual GNU command line syntax, with long options starting with two dashes (`-'). A summary of options is included below. For a complete description, see the Info files. .TP .B \-h, \-\-help Print command line help and exit .TP .B \-v, \-\-version Print version information and exit .TP .B \-b, \-\-batch Batch mode (exit after processing command line) .TP .B \-s, \-\-save Save command line changes to model files .TP .B \-\-convert [format] Save models to format [format] .TP .B \-\-no-plugins Disable all plugins .TP .B \-\-no-plugin [foo] Disable plugin [foo] .TP .B \-\-sysinfo Display system information (for bug reports) .TP .B \-\-debug Display debug messages in console .TP .B \-\-warnings Display warning messages in console .TP .B \-\-errors Display error messages in console .TP .B \-\-no-debug Do not display debug messages in console .TP .B \-\-no-warnings Do not display warning messages in console .TP .B \-\-no-errors Do not display error messages in console .SH SEE ALSO .BR blender (1), .BR wings3d (1). .SH AUTHOR mm3d was written by Kevin Worcester. .PP This manual page was written by G\[:u]rkan Seng\[:u]n , for the Debian project (but may be used by others). mm3d-1.3.7/NEWS0000644000175000017500000000052310744511356010010 00000000000000This is not the NEWS you're looking for. See README for general information See INSTALL for installation instructions See INSTALL.WIN32 for build and install instructions for Windows See COPYING for license (GPL) See ChangeLog for a list of changes since the last version See AUTHORS to find out who is to blame for this software mm3d-1.3.7/Makefile.in0000644000175000017500000004701511025503560011354 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = . am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ TODO config.guess config.sub depcomp install-sh missing \ mkinstalldirs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno configure.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BYTEORDER = @BYTEORDER@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_PROFILE = @CORE_PROFILE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLOPEN_LIBS = @DLOPEN_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ HAVE_QT4 = @HAVE_QT4@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ LUALIB_CCFLAGS = @LUALIB_CCFLAGS@ LUALIB_DIR = @LUALIB_DIR@ LUALIB_LIBS = @LUALIB_LIBS@ LUA_CCFLAGS = @LUA_CCFLAGS@ LUA_DIR = @LUA_DIR@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PROFILE = @PROFILE@ QGL_LIBS = @QGL_LIBS@ QT_CXXFLAGS = @QT_CXXFLAGS@ QT_DIR = @QT_DIR@ QT_LIBS = @QT_LIBS@ QT_LRELEASE = @QT_LRELEASE@ QT_MOC = @QT_MOC@ QT_UIC = @QT_UIC@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ EXTRA_DIST = Makefile.mingw \ config.h.mingw \ cleanup.sh \ mm3d-win32-installer.nsi \ TRANSLATORS \ INSTALL.WIN32 \ install.bat \ mm3d.reg SUBDIRS = src plugins i18n doc desktop man DESTDIR = src MAC_APP = $(PACKAGE).app all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \ cd $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) cd $(top_srcdir) && $(AUTOHEADER) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-exec-am: install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \ check-am clean clean-generic clean-recursive ctags \ ctags-recursive dist dist-all dist-bzip2 dist-gzip dist-shar \ dist-tarZ dist-zip distcheck distclean distclean-generic \ distclean-hdr distclean-recursive distclean-tags \ distcleancheck distdir distuninstallcheck dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-recursive \ mostlyclean mostlyclean-generic mostlyclean-recursive pdf \ pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ uninstall-info-am $(MAC_APP): $(MAC_APP)/Contents/PkgInfo $(MAC_APP)/Contents/Info.plist @cp $(DESTDIR)/$(PACKAGE) $(MAC_APP)/Contents/MacOS/$(PACKAGE) $(MAC_APP)/Contents/PkgInfo: @test -d $(MAC_APP)/Contents/MacOS/ || mkdir -p $(MAC_APP)/Contents/MacOS/ @rm -f $(MAC_APP)/Contents/PkgInfo @echo "APPL????" > $(MAC_APP)/Contents/PkgInfo $(MAC_APP)/Contents/Info.plist: @test -d $(MAC_APP)/Contents/MacOS/ || mkdir -p $(MAC_APP)/Contents/MacOS/ @rm -f $(MAC_APP)/Contents/Info.plist @echo "" > $(MAC_APP)/Contents/Info.plist @defaults write $(PWD)/$(MAC_APP)/Contents/Info '{"CFBundlePackageType"=APPL;}'; @defaults write $(PWD)/$(MAC_APP)/Contents/Info "CFBundleSignature" "????" @defaults write $(PWD)/$(MAC_APP)/Contents/Info "CFBundleExecutable" $(PACKAGE) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mm3d-1.3.7/acinclude.m40000644000175000017500000012632011025050654011476 00000000000000AC_DEFUN([KSW_IS_PROFILE], [ AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING(for profile) AC_ARG_ENABLE([profile], [ --enable-profile=yes/no/core Specify "yes" or "core" to enable profiling.]) is_profile=no PROFILE= CORE_PROFILE= if test x"$enable_profile" = xyes; then PROFILE=-pg CORE_PROFILE=-pg is_profile=yes elif test x"$enable_profile" = xcore; then CORE_PROFILE=-pg is_profile="yes (core)" fi AC_DEFINE( [PROFILE], [], [Define to include profilling information] ) AC_DEFINE( [CORE_PROFILE], [], [Define to include core profilling information] ) AC_MSG_RESULT($is_profile) ]) AC_DEFUN([KSW_IS_DEBUG], [ AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING(for debug) AC_ARG_ENABLE([debug], [ --enable-debug=yes/no/cov Specify "yes" to enable a debug build.]) is_debug=no enable_debug_save_COVFLAGS="${COVFLAGS}" enable_debug_save_COVLFLAGS="${COVLFLAGS}" enable_debug_save_CFLAGS="${CFLAGS}" enable_debug_save_CXXFLAGS="${CXXFLAGS}" enable_debug_save_LDFLAGS="${LDFLAGS}" if test x"$enable_debug" = xyes; then COVFLAGS="" COVLFLAGS="" CFLAGS="-g" CXXFLAGS="${CFLAGS}" LDFLAGS="" elif test x"$enable_debug" = xcov; then COVFLAGS="-coverage" COVLFLAGS="-lgcov" CFLAGS="-g" CXXFLAGS="${CFLAGS}" LDFLAGS="" is_debug=coverage else omit_frame= if test x"${CORE_PROFILE}" = "x"; then omit_frame="-fomit-frame-pointer" fi COVFLAGS="" COVLFLAGS="" CFLAGS="-O2 ${omit_frame} -fno-math-errno" CXXFLAGS="${CFLAGS}" LDFLAGS="${omit_frame} -fno-math-errno" fi AC_TRY_LINK([#include ], , [ dnl Yay! if test x"$enable_debug" = xyes; then AC_DEFINE( [CODE_DEBUG], [], [Define to include debugging information] ) is_debug=yes fi ], [ dnl Boo! if test x"$enable_debug" != xyes; then COVFLAGS="${enable_debug_save_COVFLAGS}" COVLFLAGS="${enable_debug_save_COVLFLAGS}" CFLAGS="${enable_debug_save_CFLAGS}" CXXFLAGS="${enable_debug_save_CXXFLAGS}" LDFLAGS="${enable_debug_save_LDFLAGS}" AC_DEFINE( [CODE_DEBUG], [], [Define to include debugging information] ) is_debug=yes else COVFLAGS="${enable_debug_save_COVFLAGS}" COVLFLAGS="${enable_debug_save_COVLFLAGS}" CFLAGS="${enable_debug_save_CFLAGS}" CXXFLAGS="${enable_debug_save_CXXFLAGS}" LDFLAGS="${enable_debug_save_LDFLAGS}" fi ]) AC_MSG_RESULT($is_debug) ]) dnl for lua (KSW was here) AC_DEFUN([KSW_HAVE_LUA], [ AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING(for lua) AC_ARG_WITH([lua-dir], [ --with-lua-dir=DIR DIR is equal to the install prefix of Lua. Header files are in DIR/include, and Library files are in DIR/lib]) AC_ARG_WITH([lua-include-dir], [ --with-lua-include-dir=DIR Lua header files are in DIR]) AC_ARG_WITH([lua-lib-dir], [ --with-lua-lib-dir=DIR Lua libraries are in DIR]) AC_ARG_WITH([lua-lib], [ --with-lua-lib=LIB Use -lLIB to link with the lua library]) if test x"$with_lua_dir" = x && test x"$with_lua_include_dir" = x && test x"$with_lua_lib_dir" = x && test x"$with_lua_lib" = x; then # user did not request Lua support, disable it have_lua="disabled" else # "yes" is a bogus option if test x"$with_lua_dir" = xyes; then with_lua_dir= fi if test x"$with_lua_include_dir" = xyes; then with_lua_include_dir= fi if test x"$with_lua_lib_dir" = xyes; then with_lua_lib_dir= fi if test x"$with_lua_lib" = xyes; then with_lua_lib= fi # No lua unless we discover otherwise have_lua=no # Check whether we are requested to link with a specific version if test x"$with_lua_lib" != x; then ksw_lua_lib="$with_lua_lib" fi # Check whether we were supplied with an answer already if test x"$with_lua_dir" != x; then have_lua=yes ksw_lua_dir="$with_lua_dir" ksw_lua_include_dir="$with_lua_dir/include" if test -d "$with_lua_dir/lib64" ; then ksw_lua_lib_dir="$with_lua_dir/lib64" else ksw_lua_lib_dir="$with_lua_dir/lib" fi # Only search for the lib if the user did not define one already if test x"$ksw_lua_lib" = x; then ksw_lua_lib="`ls $ksw_lua_lib_dir/liblua5* 2> /dev/null | sed -n 1p | sed s@$ksw_lua_lib_dir/lib@@ | [sed s@[.].*@@]`" fi if test x"$ksw_lua_lib" = x; then ksw_lua_lib="`ls $ksw_lua_lib_dir/liblua.* 2> /dev/null | sed -n 1p | sed s@$ksw_lua_lib_dir/lib@@ | [sed s@[.].*@@]`" fi ksw_lua_LIBS="-L$ksw_lua_lib_dir -l$ksw_lua_lib -lm -ldl" else # Use cached value or do search, starting with suggestions from # the command line AC_CACHE_VAL(ksw_cv_have_lua, [ # We are not given a solution and there is no cached value. ksw_lua_dir= if test x"$ksw_lua_include_dir" = x; then ksw_lua_include_dir="`ls -dr /usr/include/lua.h /usr/local/include/lua.h /usr/include/lua*/lua.h /usr/local/include/lua*/lua.h 2> /dev/null | sed -n 1p | sed s@/lua.h@@`" fi if test x"$ksw_lua_lib" = x; then ksw_lua_lib_dir="`ls -dr /usr/lib64/liblua5* /usr/lib64/liblua.* /usr/local/lib64/liblua5* /usr/local/lib64/liblua.* /usr/lib/liblua5* /usr/lib/liblua.* /usr/local/lib/liblua5* /usr/local/lib/liblua.* 2> /dev/null | sed -n 1p`" ksw_lua_lib="`echo $ksw_lua_lib_dir | sed 's@/.*/@@' `" ksw_lua_lib_dir="`echo $ksw_lua_lib_dir | sed s@/$ksw_lua_lib@@ `" ksw_lua_lib="`echo $ksw_lua_lib | [sed s@[.].*@@] | sed s@^lib@@ `" fi if test x"$ksw_lua_lib" != x; then if test x"$ksw_lua_lib_dir" = x; then ksw_lua_LIBS="-l$ksw_lua_lib -lm -ldl" else ksw_lua_LIBS="-L$ksw_lua_lib_dir -l$ksw_lua_lib -lm -ldl" fi # Record where we found lua for the cache. ksw_cv_have_lua="have_lua=yes \ ksw_lua_dir=$ksw_lua_dir \ ksw_lua_include_dir=$ksw_lua_include_dir \ ksw_lua_LIBS=\"$ksw_lua_LIBS\"" fi ])dnl eval "$ksw_cv_have_lua" fi # all $ksw_lua_* are set fi # $have_lua reflects the system status if test x"$have_lua" = xyes; then LUA_CCFLAGS="-I$ksw_lua_include_dir" LUA_DIR="$ksw_lua_dir" LUA_LIBS="$ksw_lua_LIBS" # All variables are defined, report the result AC_DEFINE( [HAVE_LUA], [], [Define when you have Lua installed] ) AC_MSG_RESULT([$have_lua: LUA_CCFLAGS=$LUA_CCFLAGS LUA_DIR=$LUA_DIR LUA_LIBS=$LUA_LIBS ]) else # lua was not found LUA_CCFLAGS= LUA_DIR= LUA_LIBS= AC_MSG_RESULT($have_lua) fi AC_SUBST(LUA_CCFLAGS) AC_SUBST(LUA_DIR) AC_SUBST(LUA_LIBS) #### Being paranoid: if test x"$have_lua" = xyes; then AC_MSG_CHECKING(correct functioning of lua installation) AC_CACHE_VAL(ksw_cv_lua_test_result, [ cat > ksw_lua_test.h << EOF EOF cat > ksw_lua_test.c << EOF #include "ksw_lua_test.h" #include #include //#include int main( int argc, char **argv ) { lua_State * L = lua_open(); //luaopen_math( L ); lua_close( L ); return( 0 ); } EOF ksw_cv_lua_test_result="failure" ksw_try_1="$CC $LUA_CCFLAGS $LUA_LIBS -o ksw_lua_test ksw_lua_test.c >/dev/null 2>ksw_lua_test_1.out" AC_TRY_EVAL(ksw_try_1) ksw_err_1=`grep -v '^ *+' ksw_lua_test_1.out | grep -v "^ksw_lua_test.{$ac_ext}\$"` if test x"$ksw_err_1" != x; then echo "$ksw_err_1" >&AC_FD_CC echo "configure: could not compile:" >&AC_FD_CC cat ksw_lua_test.c >&AC_FD_CC else ksw_cv_lua_test_result="success" fi fi ])dnl AC_CACHE_VAL ksw_cv_lua_test_result AC_MSG_RESULT([$ksw_cv_lua_test_result]); if test x"$ksw_cv_lua_test_result" = "xfailure"; then AC_MSG_ERROR([Failed to find matching components of a complete lua installation. Try using more options, see ./configure --help.]) fi rm -f ksw_lua_test.h \ ksw_lua_test.c ksw_lua_test.o ksw_lua_test \ ksw_lua_test_1.out ]) dnl for lualib (KSW was here) AC_DEFUN([KSW_HAVE_LUALIB], [ if test x"${LUA_LIBS}" != x; then AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([KSW_HAVE_LUA]) AC_MSG_CHECKING(for lualib) AC_ARG_WITH([lualib-dir], [ --with-lualib-dir=DIR DIR is equal to the install prefix of Lualib. Header files are in DIR/include, and Library files are in DIR/lib]) AC_ARG_WITH([lualib-include-dir], [ --with-lualib-include-dir=DIR Lua header files are in DIR]) AC_ARG_WITH([lualib-lib-dir], [ --with-lualib-lib-dir=DIR Lua libraries are in DIR]) AC_ARG_WITH([lualib-lib], [ --with-lualib-lib=LIB Use -lLIB to link with the lualib library]) if test x"$with_lualib_dir" = x"no" || test x"$with_lualib_include_dir" = x"no" || test x"$with_lualib_lib_dir" = x"no" || test x"$with_lualib_lib" = x"no"; then # user disabled lualib. Leave cache alone. have_lualib="User disabled lualib." else # "yes" is a bogus option if test x"$with_lualib_dir" = xyes; then with_lualib_dir= fi if test x"$with_lualib_include_dir" = xyes; then with_lualib_include_dir= fi if test x"$with_lualib_lib_dir" = xyes; then with_lualib_lib_dir= fi if test x"$with_lualib_lib" = xyes; then with_lualib_lib= fi # No lualib unless we discover otherwise have_lualib=no # Check whether we are requested to link with a specific version if test x"$with_lualib_lib" != x; then ksw_lualib_lib="$with_lualib_lib" fi # Check whether we were supplied with an answer already if test x"$with_lualib_dir" != x; then have_lualib=yes ksw_lualib_dir="$with_lualib_dir" ksw_lualib_include_dir="$with_lualib_dir/include" if test -d "$with_lualib_dir/lib64" ; then ksw_lualib_lib_dir="$with_lualib_dir/lib64" else ksw_lualib_lib_dir="$with_lualib_dir/lib" fi # Only search for the lib if the user did not define one already if test x"$ksw_lualib_lib" = x; then ksw_lualib_lib="`ls $ksw_lualib_lib_dir/liblualib5* 2> /dev/null | sed -n 1p | sed s@$ksw_lualib_lib_dir/lib@@ | [sed s@[.].*@@]`" fi if test x"$ksw_lualib_lib" = x; then ksw_lualib_lib="`ls $ksw_lualib_lib_dir/liblualib.* 2> /dev/null | sed -n 1p | sed s@$ksw_lualib_lib_dir/lib@@ | [sed s@[.].*@@]`" fi ksw_lualib_LIBS="-L$ksw_lualib_lib_dir -l$ksw_lualib_lib" else # Use cached value or do search, starting with suggestions from # the command line AC_CACHE_VAL(ksw_cv_have_lualib, [ # We are not given a solution and there is no cached value. ksw_lualib_dir= if test x"$ksw_lualib_include_dir" = x; then ksw_lualib_include_dir="`ls -dr /usr/include/lualib.h /usr/local/include/lualib.h /usr/include/lua*/lualib.h /usr/local/include/lua*/lualib.h 2> /dev/null | sed -n 1p | sed s@/lualib.h@@`" fi if test x"$ksw_lualib_lib" = x; then ksw_lualib_lib_dir="`ls -dr /usr/lib64/liblualib5* /usr/lib64/liblualib.* /usr/local/lib64/liblualib5* /usr/local/lib64/liblualib.* /usr/lib/liblualib5* /usr/lib/liblualib.* /usr/local/lib/liblualib5* /usr/local/lib/liblualib.* 2> /dev/null | sed -n 1p`" ksw_lualib_lib="`echo $ksw_lualib_lib_dir | sed 's@/.*/@@' `" ksw_lualib_lib_dir="`echo $ksw_lualib_lib_dir | sed s@/$ksw_lualib_lib@@ `" ksw_lualib_lib="`echo $ksw_lualib_lib | [sed s@[.].*@@] | sed s@^lib@@ `" fi if test x"$ksw_lualib_lib" != x; then if test x"$ksw_lualib_lib_dir" = x; then ksw_lualib_LIBS="-l$ksw_lualib_lib" else ksw_lualib_LIBS="-L$ksw_lualib_lib_dir -l$ksw_lualib_lib" fi # Record where we found lualib for the cache. ksw_cv_have_lualib="have_lualib=yes \ ksw_lualib_dir=$ksw_lualib_dir \ ksw_lualib_include_dir=$ksw_lualib_include_dir \ ksw_lualib_LIBS=\"$ksw_lualib_LIBS\"" fi ])dnl eval "$ksw_cv_have_lualib" fi # all $ksw_lualib_* are set fi # $have_lualib reflects the system status if test x"$have_lualib" = xyes; then LUALIB_CCFLAGS="-I$ksw_lualib_include_dir" LUALIB_DIR="$ksw_lualib_dir" LUALIB_LIBS="-lm -ldl $LUA_LIBS $ksw_lualib_LIBS" # All variables are defined, report the result AC_DEFINE( [HAVE_LUALIB], [], [Define when you have Lua libs installed] ) AC_MSG_RESULT([$have_lualib: LUALIB_CCFLAGS=$LUALIB_CCFLAGS LUALIB_DIR=$LUALIB_DIR LUALIB_LIBS=$LUALIB_LIBS ]) else # lualib was not found LUALIB_CCFLAGS= LUALIB_DIR= LUALIB_LIBS= AC_MSG_RESULT($have_lualib) fi AC_SUBST(LUALIB_CCFLAGS) AC_SUBST(LUALIB_DIR) AC_SUBST(LUALIB_LIBS) #### Being paranoid: if test x"$have_lualib" = xyes; then AC_MSG_CHECKING(correct functioning of lualib installation) AC_CACHE_VAL(ksw_cv_lualib_test_result, [ cat > ksw_lualib_test.h << EOF EOF cat > ksw_lualib_test.c << EOF #include "ksw_lualib_test.h" #include #include #include int main( int argc, char **argv ) { lua_State * L = lua_open(); luaopen_math( L ); lua_close( L ); return( 0 ); } EOF ksw_cv_lualib_test_result="failure" ksw_try_1="$CC $LUALIB_CCFLAGS $LUALIB_LIBS -o ksw_lualib_test ksw_lualib_test.c >/dev/null 2>ksw_lualib_test_1.out" AC_TRY_EVAL(ksw_try_1) ksw_err_1=`grep -v '^ *+' ksw_lualib_test_1.out | grep -v "^ksw_lualib_test.{$ac_ext}\$"` if test x"$ksw_err_1" != x; then echo "$ksw_err_1" >&AC_FD_CC echo "configure: could not compile:" >&AC_FD_CC cat ksw_lualib_test.c >&AC_FD_CC else ksw_cv_lualib_test_result="success" fi fi ])dnl AC_CACHE_VAL ksw_cv_lualib_test_result AC_MSG_RESULT([$ksw_cv_lualib_test_result]); if test x"$ksw_cv_lualib_test_result" = "xfailure"; then AC_MSG_ERROR([Failed to find matching components of a complete lualib installation. Try using more options, see ./configure --help.]) fi rm -f ksw_lualib_test.h \ ksw_lualib_test.c ksw_lualib_test.o ksw_lualib_test \ ksw_lualib_test_1.out fi ]) dnl for Qt (KSW was here) AC_DEFUN([BNV_HAVE_QT], [ dnl THANKS! This code includes bug fixes by: dnl Tim McClarren. AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([AC_PATH_X]) AC_REQUIRE([AC_PATH_XTRA]) AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_MSG_CHECKING(for Qt) QT_XLIBS="$X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" if test x"$no_x" = xyes; then QT_XLIBS="" fi dnl KSW hackish... requires another macro to set is_osx if test x"$is_osx" = xyes; then QT_XLIBS="" fi AC_ARG_WITH([Qt-dir], [ --with-Qt-dir=DIR DIR is equal to \$QTDIR if you have followed the installation instructions of Trolltech. Header files are in DIR/include, binary utilities are in DIR/bin and the library is in DIR/lib]) AC_ARG_WITH([Qt-include-dir], [ --with-Qt-include-dir=DIR Qt header files are in DIR]) AC_ARG_WITH([Qt-bin-dir], [ --with-Qt-bin-dir=DIR Qt utilities such as moc and uic are in DIR]) AC_ARG_WITH([Qt-lib-dir], [ --with-Qt-lib-dir=DIR The Qt library is in DIR]) dnl FIXME moc-qt4 and uic-qt4 bnv_is_qt4=no bnv_qt4_libs="-lQtCore -lQtGui -lQtOpenGL -lQtNetwork" if test x"$with_Qt_dir" = x"no" || test x"$with_Qt_include_dir" = x"no" || test x"$with_Qt_bin_dir" = x"no" || test x"$with_Qt_lib_dir" = x"no"; then # user disabled Qt. Leave cache alone. have_qt="User disabled Qt." else # "yes" is a bogus option if test x"$with_Qt_dir" = xyes; then with_Qt_dir= fi if test x"$with_Qt_include_dir" = xyes; then with_Qt_include_dir= fi if test x"$with_Qt_bin_dir" = xyes; then with_Qt_bin_dir= fi if test x"$with_Qt_lib_dir" = xyes; then with_Qt_lib_dir= fi # No Qt unless we discover otherwise have_qt=no # Check whether we were supplied with an answer already if test x"$with_Qt_dir" != x; then have_qt=yes bnv_qt_dir="$with_Qt_dir" bnv_qt_include_dir="$with_Qt_dir/include" bnv_qt_bin_dir="$with_Qt_dir/bin" if test -d "$with_Qt_dir/lib64" ; then bnv_qt_lib_dir="$with_Qt_dir/lib64" else bnv_qt_lib_dir="$with_Qt_dir/lib" fi bnv_qt_LIBS="-L$bnv_qt_lib_dir $bnv_qt4_libs $QT_XLIBS " else # Use cached value or do search, starting with suggestions from # the command line AC_CACHE_VAL(bnv_cv_have_qt, [ # We are not given a solution and there is no cached value. bnv_qt_dir=NO bnv_qt_include_dir=NO bnv_qt_lib_dir=NO BNV_PATH_QT_DIRECT if test "$bnv_qt_dir" = NO || test "$bnv_qt_include_dir" = NO || test "$bnv_qt_lib_dir" = NO; then # Problem with finding complete Qt. Cache the known absence of Qt. bnv_cv_have_qt="have_qt=no" else # Record where we found Qt for the cache. bnv_cv_have_qt="have_qt=yes \ bnv_qt_dir=$bnv_qt_dir \ bnv_qt_include_dir=$bnv_qt_include_dir \ bnv_qt_bin_dir=$bnv_qt_bin_dir \ bnv_is_qt4=$bnv_is_qt4 \ bnv_qt_LIBS=\"$bnv_qt_LIBS\"" fi ])dnl eval "$bnv_cv_have_qt" fi # all $bnv_qt_* are set fi # $have_qt reflects the system status if test x"$have_qt" = xyes; then QT_CXXFLAGS="-I$bnv_qt_include_dir" QT_DIR="$bnv_qt_dir" QT_LIBS="$bnv_qt_LIBS" if test x"$bnv_qt_bin_dir" != x; then # We were told where to look for the utilities? # UIC detection if test -x "$bnv_qt_bin_dir/uic-qt4"; then QT_UIC="$bnv_qt_bin_dir/uic-qt4" elif test -x "$bnv_qt_bin_dir/qt4-uic"; then QT_UIC="$bnv_qt_bin_dir/qt4-uic" elif test -x "$bnv_qt_bin_dir/uic"; then QT_UIC="$bnv_qt_bin_dir/uic" fi # MOC detection if test -x "$bnv_qt_bin_dir/moc-qt4"; then QT_MOC="$bnv_qt_bin_dir/moc-qt4" elif test -x "$bnv_qt_bin_dir/qt4-moc"; then QT_MOC="$bnv_qt_bin_dir/qt4-moc" elif test -x "$bnv_qt_bin_dir/moc"; then QT_MOC="$bnv_qt_bin_dir/moc" fi # LRELEASE detection if test -x "$bnv_qt_bin_dir/lrelease-qt4"; then QT_LRELEASE="$bnv_qt_bin_dir/lrelease-qt4" elif test -x "$bnv_qt_bin_dir/qt4-lrelease"; then QT_LRELEASE="$bnv_qt_bin_dir/qt4-lrelease" elif test -x "$bnv_qt_bin_dir/lrelease"; then QT_LRELEASE="$bnv_qt_bin_dir/lrelease" fi elif test x"$bnv_qt_dir" != x; then # If bnv_qt_dir is defined, utilities are expected to be in the # bin subdirectory # UIC detection if test -x "$bnv_qt_dir/bin/uic-qt4"; then QT_UIC="$bnv_qt_dir/bin/uic-qt4" elif test -x "$bnv_qt_dir/bin/qt4-uic"; then QT_UIC="$bnv_qt_dir/bin/qt4-uic" elif test -x "$bnv_qt_dir/bin/uic"; then QT_UIC="$bnv_qt_dir/bin/uic" fi # MOC detection if test -x "$bnv_qt_dir/bin/moc-qt4"; then QT_MOC="$bnv_qt_dir/bin/moc-qt4" elif test -x "$bnv_qt_dir/bin/qt4-moc"; then QT_MOC="$bnv_qt_dir/bin/qt4-moc" elif test -x "$bnv_qt_dir/bin/moc"; then QT_MOC="$bnv_qt_dir/bin/moc" fi # LRELEASE detection if test -x "$bnv_qt_dir/bin/lrelease-qt4"; then QT_LRELEASE="$bnv_qt_dir/bin/lrelease-qt4" elif test -x "$bnv_qt_dir/bin/qt4-lrelease"; then QT_LRELEASE="$bnv_qt_dir/bin/qt4-lrelease" elif test -x "$bnv_qt_dir/bin/lrelease"; then QT_LRELEASE="$bnv_qt_dir/bin/lrelease" fi fi # If binaries are still not set, try $PATH if test x"$QT_UIC" = x; then # UIC detection if test `which uic-qt4 2> /dev/null`; then QT_UIC=`which uic-qt4` elif test `which qt4-uic 2> /dev/null`; then QT_UIC=`which qt4-uic` elif test `which uic 2> /dev/null`; then QT_UIC=`which uic` fi fi if test x"$QT_MOC" = x; then # MOC detection if test `which moc-qt4 2> /dev/null`; then QT_MOC=`which moc-qt4` elif test `which qt4-moc 2> /dev/null`; then QT_MOC=`which qt4-moc` elif test `which moc 2> /dev/null`; then QT_MOC=`which moc` fi fi if test x"$QT_LRELEASE" = x; then # LRELEASE detection if test `which lrelease-qt4 2> /dev/null`; then QT_LRELEASE=`which lrelease-qt4` elif test `which qt4-lrelease 2> /dev/null`; then QT_LRELEASE=`which qt4-lrelease` elif test `which lrelease 2> /dev/null`; then QT_LRELEASE=`which lrelease` fi fi # All variables are defined, report the result AC_MSG_RESULT([$have_qt: QT_CXXFLAGS=$QT_CXXFLAGS QT_DIR=$QT_DIR QT_LIBS=$QT_LIBS QT_UIC=$QT_UIC QT_MOC=$QT_MOC QT_LRELEASE=$QT_LRELEASE]) else # Qt was not found QT_CXXFLAGS= QT_DIR= QT_LIBS= QT_UIC= QT_MOC= QT_LRELEASE= AC_MSG_RESULT($have_qt) fi if test x"$bnv_is_qt4" = xyes; then HAVE_QT4=1 AC_SUBST(HAVE_QT4) AC_DEFINE( [HAVE_QT4], [], [Define when you have QT4 installed] ) fi AC_SUBST(QT_CXXFLAGS) AC_SUBST(QT_DIR) AC_SUBST(QT_LIBS) AC_SUBST(QT_UIC) AC_SUBST(QT_MOC) AC_SUBST(QT_LRELEASE) #### Being paranoid: if test x"$have_qt" = xyes; then AC_MSG_CHECKING(correct functioning of Qt installation) AC_CACHE_VAL(bnv_cv_qt_test_result, [ cat > bnv_qt_test.h << EOF #include class Test : public QObject { Q_OBJECT public: Test() {} ~Test() {} public slots: void receive() {} signals: void send(); }; EOF cat > bnv_qt_main.$ac_ext << EOF #include "bnv_qt_test.h" #include int main( int argc, char **argv ) { QApplication app( argc, argv ); Test t; QObject::connect( &t, SIGNAL(send()), &t, SLOT(receive()) ); } EOF bnv_cv_qt_test_result="failure" bnv_try_1="$QT_MOC bnv_qt_test.h -o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_1.out" AC_TRY_EVAL(bnv_try_1) bnv_err_1=`grep -v '^ *+' bnv_qt_test_1.out | grep -v "^bnv_qt_test.h\$"` if test x"$bnv_err_1" != x; then echo "$bnv_err_1" >&AC_FD_CC echo "configure: could not run $QT_MOC on:" >&AC_FD_CC cat bnv_qt_test.h >&AC_FD_CC else bnv_try_2="$CXX $QT_CXXFLAGS -c $CXXFLAGS -Wno-non-virtual-dtor -o moc_bnv_qt_test.o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_2.out" AC_TRY_EVAL(bnv_try_2) bnv_err_2=`grep -v '^ *+' bnv_qt_test_2.out | grep -v "^bnv_qt_test.{$ac_ext}\$"` if test x"$bnv_err_2" != x; then echo "$bnv_err_2" >&AC_FD_CC echo "configure: could not compile:" >&AC_FD_CC cat bnv_qt_test.$ac_ext >&AC_FD_CC else bnv_try_3="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o bnv_qt_main.o bnv_qt_main.$ac_ext >/dev/null 2>bnv_qt_test_3.out" AC_TRY_EVAL(bnv_try_3) bnv_err_3=`grep -v '^ *+' bnv_qt_test_3.out | grep -v "^bnv_qt_main.{$ac_ext}\$"` if test x"$bnv_err_3" != x; then echo "$bnv_err_3" >&AC_FD_CC echo "configure: could not compile:" >&AC_FD_CC cat bnv_qt_main.$ac_ext >&AC_FD_CC else bnv_try_4="$CXX $QT_LIBS $LIBS -o bnv_qt_main bnv_qt_main.o moc_bnv_qt_test.o >/dev/null 2>bnv_qt_test_4.out" AC_TRY_EVAL(bnv_try_4) bnv_err_4=`grep -v '^ *+' bnv_qt_test_4.out` if test x"$bnv_err_4" != x; then echo "$bnv_err_4" >&AC_FD_CC else bnv_cv_qt_test_result="success" fi fi fi fi ])dnl AC_CACHE_VAL bnv_cv_qt_test_result AC_MSG_RESULT([$bnv_cv_qt_test_result]); if test x"$bnv_cv_qt_test_result" = "xfailure"; then AC_MSG_ERROR([Failed to find matching components of a complete Qt installation. Try using more options, see ./configure --help.]) fi rm -f bnv_qt_test.h moc_bnv_qt_test.$ac_ext moc_bnv_qt_test.o \ bnv_qt_main.$ac_ext bnv_qt_main.o bnv_qt_main \ bnv_qt_test_1.out bnv_qt_test_2.out bnv_qt_test_3.out bnv_qt_test_4.out fi AC_LANG_RESTORE ]) dnl Internal subroutine of BNV_HAVE_QT dnl Set bnv_qt_dir bnv_qt_include_dir bnv_qt_bin_dir bnv_qt_lib_dir dnl Copyright 2001 Bastiaan N. Veelo AC_DEFUN([BNV_PATH_QT_DIRECT], [ ## Binary utilities ## if test x"$with_Qt_bin_dir" != x; then bnv_qt_bin_dir=$with_Qt_bin_dir fi ## Look for header files ## if test x"$with_Qt_include_dir" != x; then bnv_qt_include_dir="$with_Qt_include_dir" else # The following header file is expected to define QT_VERSION. # Look for the header file in a standard set of common directories. qt_direct_test_header=qglobal.h bnv_include_path_list=" /usr/include `ls -dr /usr/include/qt* 2>/dev/null` `ls -dr /usr/lib/qt*/include 2>/dev/null` `ls -dr /usr/local/qt*/include 2>/dev/null` `ls -dr /opt/sfw/include 2>/dev/null` `ls -dr /opt/qt*/include 2>/dev/null` `ls -dr /usr/qt*/include 2>/dev/null` `ls -dr /usr/qt/*/include 2>/dev/null` `ls -dr /usr/include/qt/* 2>/dev/null` " for bnv_dir in $bnv_include_path_list; do if test -r "$bnv_dir/Qt/$qt_direct_test_header"; then bnv_dirs="$bnv_dirs $bnv_dir" fi done # Now look for the newest in this list bnv_prev_ver=0 for bnv_dir in $bnv_dirs; do if test -r "$bnv_dir/Qt/$qt_direct_test_header"; then bnv_this_ver=`egrep -w '#define QT_VERSION' $bnv_dir/Qt/$qt_direct_test_header | sed s/'#define QT_VERSION'//` if expr $bnv_this_ver '>' $bnv_prev_ver > /dev/null; then bnv_is_qt4=yes bnv_qt_include_dir=$bnv_dir bnv_prev_ver=$bnv_this_ver fi fi done fi dnl Found header files. # Are these headers located in a traditional Trolltech installation? # That would be $bnv_qt_include_dir stripped from its last element: bnv_found_traditional=no bnv_possible_qt_dir=`dirname $bnv_qt_include_dir` if test -x $bnv_possible_qt_dir/bin/moc-qt4 && ls $bnv_possible_qt_dir/lib/libQtCore* 1> /dev/null 2> /dev/null; then bnv_found_traditional=yes elif test -x $bnv_possible_qt_dir/bin/moc && ls $bnv_possible_qt_dir/lib/libQtCore.* 1> /dev/null 2> /dev/null; then bnv_found_traditional=yes fi if test x"$bnv_found_traditional" = xyes; then # Then the rest is a piece of cake bnv_qt_dir=$bnv_possible_qt_dir bnv_qt_bin_dir="$bnv_qt_dir/bin" if test -d "$bnv_qt_dir/lib64" ; then bnv_qt_lib_dir="$bnv_qt_dir/lib64" else bnv_qt_lib_dir="$bnv_qt_dir/lib" fi bnv_qt_LIBS="-L$bnv_qt_lib_dir $bnv_qt4_libs $QT_XLIBS" fi if test $bnv_found_traditional = no; then # There is no valid definition for $QTDIR as Trolltech likes to see it bnv_qt_dir= ## Look for Qt library ## if test x"$with_Qt_lib_dir" != x; then bnv_qt_lib_dir="$with_Qt_lib_dir" bnv_qt_LIBS="-L$bnv_qt_lib_dir $bnv_qt4_libs $QT_XLIBS" else # Normally, when there is no traditional Trolltech installation, # the library is installed in a place where the linker finds it # automatically. qt_direct_test_header=qapplication.h qt_direct_test_main=" int argc; char ** argv; QApplication app(argc,argv); " # See if we find the library without any special options. # Don't add top $LIBS permanently yet bnv_save_LIBS="$LIBS" bnv_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="-I$bnv_qt_include_dir" LIBS="$bnv_qt4_libs $QT_XLIBS" bnv_qt_LIBS="$LIBS" AC_TRY_LINK([#include <$qt_direct_test_header>], $qt_direct_test_main, [ # Succes. # We can link with no special library directory. bnv_qt_lib_dir= ], [ # That did not work. Maybe a library version I don't know about? # Look for some Qt lib in a standard set of common directories. bnv_dir_list=" `echo $bnv_qt_includes | sed ss/includess` /lib /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /opt/lib64 /opt/lib `ls -dr /usr/lib/qt* 2>/dev/null` `ls -dr /usr/local/qt* 2>/dev/null` `ls -dr /opt/qt* 2>/dev/null` " for bnv_dir in $bnv_dir_list; do if ls $bnv_dir/libQtCore* > /dev/null 2> /dev/null ; then bnv_qt_lib_dir="$bnv_dir" break fi done # Try with that one LIBS="$bnv_qt4_libs $QT_XLIBS" ]) if test x"$bnv_qt_lib_dir" != x; then bnv_qt_LIBS="-L$bnv_qt_lib_dir $LIBS" else bnv_qt_LIBS="$LIBS" fi LIBS="$bnv_save_LIBS" CXXFLAGS="$bnv_save_CXXFLAGS" fi dnl $with_Qt_lib_dir was not given fi dnl Done setting up for non-traditional Trolltech installation ]) dnl for -lqglviewer (KSW was here) AC_DEFUN([KSW_HAVE_QGL], [ AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([BNV_HAVE_QT]) AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_MSG_CHECKING(Qt OpenGL) AC_CACHE_VAL(ksw_cv_qgl_test_result, [ cat > ksw_qgl_test.${ac_ext} << EOF #include #include #include int main( int argc, char ** argv ) { QApplication app( argc, argv ); QGLWidget w; w.show(); return app.exec(); } EOF ksw_cv_qgl_test_result="failure" ksw_try_1="$CXX $GL_CFLAGS $GL_LIBS $QT_CXXFLAGS $QT_LIBS -o ksw_qgl_test ksw_qgl_test.${ac_ext} >/dev/null 2>ksw_qgl_test_1.out" AC_TRY_EVAL(ksw_try_1) ksw_err_1=`grep -v '^ *+' ksw_qgl_test_1.out | grep -v "^ksw_qgl_test.{$ac_ext}\$"` if test x"$ksw_err_1" != x; then ksw_try_2="$CXX $GL_CFLAGS $GL_LIBS $QT_CXXFLAGS $QT_LIBS -lqglviewer -o ksw_qgl_test ksw_qgl_test.${ac_ext} >/dev/null 2>ksw_qgl_test_2.out" AC_TRY_EVAL(ksw_try_2) ksw_err_2=`grep -v '^ *+' ksw_qgl_test_2.out | grep -v "^ksw_qgl_test.{$ac_ext}\$"` if test x"$ksw_err_2" != x; then echo "$ksw_err_2" >&AC_FD_CC echo "configure: could not compile:" >&AC_FD_CC cat ksw_qgl_test.${ac_ext} >&AC_FD_CC else ksw_cv_qgl_test_result="success" QGL_LIBS=-lqglviewer fi else ksw_cv_qgl_test_result="success" QGL_LIBS= fi ])dnl AC_CACHE_VAL ksw_cv_qgl_test_result AC_MSG_RESULT([$ksw_cv_qgl_test_result]); if test x"$ksw_cv_qgl_test_result" = "xfailure"; then AC_MSG_ERROR([Failed to link Qt with OpenGL support.]) fi rm -f ksw_qgl_test.h \ ksw_qgl_test.${ac_ext} ksw_qgl_test.o ksw_qgl_test \ ksw_qgl_test_1.out ksw_qgl_test_2.out AC_SUBST(QGL_LIBS) AC_LANG_RESTORE ]) AC_DEFUN([MDL_HAVE_OPENGL], [ AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_PATH_X]) AC_REQUIRE([AC_PATH_XTRA]) AC_CACHE_CHECK([for OpenGL], mdl_cv_have_OpenGL, [ dnl Check for Mesa first, unless we were asked not to. AC_ARG_WITH([--with-Mesa], [Prefer the Mesa library over a vendors native OpenGL library (default=yes)], with_Mesa_help_string) AC_ARG_ENABLE(Mesa, $with_Mesa_help_string, use_Mesa=$enableval, use_Mesa=yes) if test x"$use_Mesa" = xyes; then GL_search_list="MesaGL GL" GLU_search_list="MesaGLU GLU" GLX_search_list="MesaGLX GLX" else GL_search_list="GL MesaGL" GLU_search_list="GLU MesaGLU" GLX_search_list="GLX MesaGLX" fi AC_LANG_SAVE AC_LANG_C if test x"$is_osx" = xyes; then GL_CFLAGS="-framework OpenGL -framework AGL" GL_LIBS="-framework OpenGL -framework AGL" else dnl If we are running under X11 then add in the appropriate libraries. if test x"$no_x" != xyes; then dnl Add everything we need to compile and link X programs to GL_X_CFLAGS dnl and GL_X_LIBS. GL_CFLAGS="$X_CFLAGS" GL_X_LIBS="$X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" fi fi GL_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$GL_CFLAGS" GL_save_LIBS="$LIBS" LIBS="$GL_X_LIBS" # Save the "AC_MSG_RESULT file descriptor" to FD 8. exec 8>&AC_FD_MSG # Temporarily turn off AC_MSG_RESULT so that the user gets pretty # messages. exec AC_FD_MSG>/dev/null AC_SEARCH_LIBS(glAccum, $GL_search_list, have_GL=yes, have_GL=no) AC_SEARCH_LIBS(gluBeginCurve, $GLU_search_list, have_GLU=yes, have_GLU=no) AC_SEARCH_LIBS(glXChooseVisual, $GLX_search_list, have_GLX=yes, have_GLX=no) AC_SEARCH_LIBS(glutInit, glut, have_glut=yes, have_glut=no) # Restore pretty messages. exec AC_FD_MSG>&8 if test -n "$LIBS"; then mdl_cv_have_OpenGL=yes GL_LIBS="$LIBS" AC_SUBST(GL_CFLAGS) AC_SUBST(GL_LIBS) else mdl_cv_have_OpenGL=no GL_CFLAGS= fi dnl Reset GL_X_LIBS regardless, since it was just a temporary variable dnl and we don't want to be global namespace polluters. GL_X_LIBS= LIBS="$GL_save_LIBS" CPPFLAGS="$GL_save_CPPFLAGS" AC_LANG_RESTORE dnl bugfix: dont forget to cache this variables, too mdl_cv_GL_CFLAGS="$GL_CFLAGS" mdl_cv_GL_LIBS="$GL_LIBS" mdl_cv_have_GL="$have_GL" mdl_cv_have_GLU="$have_GLU" mdl_cv_have_GLX="$have_GLX" mdl_cv_have_glut="$have_glut" ]) GL_CFLAGS="$mdl_cv_GL_CFLAGS" GL_LIBS="$mdl_cv_GL_LIBS" have_GL="$mdl_cv_have_GL" have_GLU="$mdl_cv_have_GLU" have_GLX="$mdl_cv_have_GLX" have_glut="$mdl_cv_have_glut" ]) dnl endof bugfix -ainan AC_DEFUN([KSW_HAVE_DLOPEN], [ AC_REQUIRE([AC_PROG_CC]) AC_CACHE_CHECK([for dlopen], ksw_cv_have_dlopen, [ DLOPEN_save_LIBS="$LIBS" if test x"$is_osx" = xyes; then DLOPEN_LIBS="-ldl" else DLOPEN_LIBS="-ldl -rdynamic" fi LIBS="$DLOPEN_save_LIBS $DLOPEN_LIBS" cat > ksw_dlopen_test.c << EOF #include #include int main( int argc, char * argv[] ) { dlopen( "filename", 0 ); return 0; } EOF if ${CC} -o ksw_dlopen_test ksw_dlopen_test.c $LIBS 2> /dev/null > /dev/null; then have_dlopen=yes else DLOPEN_LIBS="-ldl -Wl,export-dynamic" LIBS="$DLOPEN_save_LIBS $DLOPEN_LIBS" if ${CC} -o ksw_dlopen_test ksw_dlopen_test.c $LIBS 2> /dev/null > /dev/null; then have_dlopen=yes else have_dlopen=no DLOPEN_LIBS= fi fi rm -f ksw_dlopen_test ksw_dlopen_test.c LIBS="$DLOPEN_save_LIBS" ksw_cv_DLOPEN_LIBS="$DLOPEN_LIBS" ksw_cv_have_dlopen="$have_dlopen" ]) DLOPEN_LIBS="$ksw_cv_DLOPEN_LIBS" have_dlopen="$ksw_cv_have_dlopen" AC_SUBST( DLOPEN_LIBS ) if test x"$have_dlopen" = "xyes"; then AC_DEFINE( [HAVE_DLOPEN], [], [Define when you have dlopen function] ) fi ]) AC_DEFUN([VL_PROG_CC_WARNINGS], [ ansi=$1 if test -z "$ansi"; then msg="for C compiler warning flags" else msg="for C compiler warning and ANSI conformance flags" fi AC_CACHE_CHECK($msg, vl_cv_prog_cc_warnings, [ if test -n "$CC"; then cat > conftest.c <&1 | grep -i "WorkShop" > /dev/null 2>&1 && $CC -c -v -Xc conftest.c > /dev/null 2>&1 && test -f conftest.o; then if test -z "$ansi"; then vl_cv_prog_cc_warnings="-v" else vl_cv_prog_cc_warnings="-v -Xc" fi dnl Digital Unix C compiler elif $CC -V 2>&1 | grep -i "Digital UNIX Compiler" > /dev/null 2>&1 && $CC -c -verbose -w0 -warnprotos -std1 conftest.c > /dev/null 2>&1 && test -f conftest.o; then if test -z "$ansi"; then vl_cv_prog_cc_warnings="-verbose -w0 -warnprotos" else vl_cv_prog_cc_warnings="-verbose -w0 -warnprotos -std1" fi dnl C for AIX Compiler elif $CC 2>&1 | grep -i "C for AIX Compiler" > /dev/null 2>&1 && $CC -c -qlanglvl=ansi -qinfo=all conftest.c > /dev/null 2>&1 && test -f conftest.o; then if test -z "$ansi"; then vl_cv_prog_cc_warnings="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" else vl_cv_prog_cc_warnings="-qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd -qlanglvl=ansi" fi dnl IRIX C compiler elif $CC -version 2>&1 | grep -i "MIPSpro Compilers" > /dev/null 2>&1 && $CC -c -fullwarn -ansi -ansiE conftest.c > /dev/null 2>&1 && test -f conftest.o; then if test -z "$ansi"; then vl_cv_prog_cc_warnings="-fullwarn" else vl_cv_prog_cc_warnings="-fullwarn -ansi -ansiE" fi dnl HP-UX C compiler elif what $CC 2>&1 | grep -i "HP C Compiler" > /dev/null 2>&1 && $CC -c -Aa +w1 conftest.c > /dev/null 2>&1 && test -f conftest.o; then if test -z "$ansi"; then vl_cv_prog_cc_warnings="+w1" else vl_cv_prog_cc_warnings="+w1 -Aa" fi dnl The NEC SX-5 (Super-UX 10) C compiler elif $CC -V 2>&1 | grep "/SX" > /dev/null 2>&1 && $CC -c -pvctl[,]fullmsg -Xc conftest.c > /dev/null 2>&1 && test -f conftest.o; then if test -z "$ansi"; then vl_cv_prog_cc_warnings="-pvctl[,]fullmsg" else vl_cv_prog_cc_warnings="-pvctl[,]fullmsg -Xc" fi dnl The Cray C compiler (Unicos) elif $CC -V 2>&1 | grep -i "Cray" > /dev/null 2>&1 && $CC -c -h msglevel 2 conftest.c > /dev/null 2>&1 && test -f conftest.o; then if test -z "$ansi"; then vl_cv_prog_cc_warnings="-h msglevel 2" else vl_cv_prog_cc_warnings="-h msglevel 2 -h conform" fi fi rm -f conftest.* fi if test -n "$vl_cv_prog_cc_warnings"; then CFLAGS="$CFLAGS $vl_cv_prog_cc_warnings" CXXFLAGS="$CXXFLAGS $vl_cv_prog_cc_warnings" else vl_cv_prog_cc_warnings="unknown" fi ]) ])dnl AC_DEFUN([AC_C_BIGENDIAN_CROSS], [AC_CACHE_CHECK(whether byte ordering is bigendian, ac_cv_c_bigendian, [ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. AC_TRY_COMPILE([#include #include ], [ #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN bogus endian macros #endif], [# It does; now see whether it defined to BIG_ENDIAN or not. AC_TRY_COMPILE([#include #include ], [ #if BYTE_ORDER != BIG_ENDIAN not big endian #endif], ac_cv_c_bigendian=yes, ac_cv_c_bigendian=no)]) if test $ac_cv_c_bigendian = unknown; then AC_TRY_RUN([main () { /* Are we little or big endian? From Harbison&Steele. */ union { long l; char c[sizeof (long)]; } u; u.l = 1; exit (u.c[sizeof (long) - 1] == 1); }], ac_cv_c_bigendian=no, ac_cv_c_bigendian=yes, [ echo $ac_n "cross-compiling... " 2>&AC_FD_MSG ]) fi]) if test $ac_cv_c_bigendian = unknown; then AC_MSG_CHECKING(to probe for byte ordering) [ cat >conftest.c <&AC_FD_MSG ac_cv_c_bigendian=yes fi if test `grep -l LiTTleEnDian conftest.o` ; then echo $ac_n ' little endian probe OK, ' 1>&AC_FD_MSG if test $ac_cv_c_bigendian = yes ; then ac_cv_c_bigendian=unknown; else ac_cv_c_bigendian=no fi fi echo $ac_n 'guessing bigendian ... ' >&AC_FD_MSG fi fi AC_MSG_RESULT($ac_cv_c_bigendian) fi if test $ac_cv_c_bigendian = yes; then AC_DEFINE(WORDS_BIGENDIAN, 1, [whether byteorder is bigendian]) BYTEORDER=4321 else BYTEORDER=1234 fi AC_DEFINE_UNQUOTED(BYTEORDER, $BYTEORDER, [1234 = LIL_ENDIAN, 4321 = BIGENDIAN]) if test $ac_cv_c_bigendian = unknown; then AC_MSG_ERROR(unknown endianess - sorry, please pre-set ac_cv_c_bigendian) fi ]) AC_DEFUN([KSW_HAVE_X11FONT], [ AC_REQUIRE([AC_PROG_CC]) AC_CACHE_CHECK([for x11 fonts], ksw_cv_have_x11font, [ cat > ksw_have_x11font_test.c << EOF #include #include int main( int argc, char * argv[] ) { glXUseXFont( 0, 0, 0, 0 ); return 0; } EOF if ${CC} -c ksw_have_x11font_test.c 2> /dev/null > /dev/null; then have_x11font=yes else have_x11font=no fi rm -f ksw_have_x11font* ksw_cv_have_x11font="$have_x11font" ]) have_x11font="$ksw_cv_have_x11font" if test x"$have_x11font" = "xyes"; then AC_DEFINE( [HAVE_XFONT], [], [Define when you have xfont] ) fi ]) AC_DEFUN([KSW_HAVE_GETTIMEOFDAY], [ AC_REQUIRE([AC_PROG_CC]) AC_CACHE_CHECK([for gettimeofday], ksw_cv_have_gettimeofday, [ cat > ksw_have_gettimeofday_test.c << EOF #include #include int main( int argc, char * argv[] ) { struct timeval tv; gettimeofday( &tv, NULL ); return 0; } EOF if ${CC} -c ksw_have_gettimeofday_test.c 2> /dev/null > /dev/null; then have_gettimeofday=yes else have_gettimeofday=no fi rm -f ksw_have_gettimeofday* ksw_cv_have_gettimeofday="$have_gettimeofday" ]) have_gettimeofday="$ksw_cv_have_gettimeofday" if test x"$have_gettimeofday" = "xyes"; then AC_DEFINE( [HAVE_GETTIMEOFDAY], [], [Define when you have gettimeofday function] ) fi ]) AC_DEFUN([KSW_IS_OSX], [ AC_REQUIRE([AC_PROG_CC]) AC_CACHE_CHECK([for OS X], ksw_cv_is_osx, [ if test -e /System/Library/Frameworks/Carbon.framework; then is_osx=yes else is_osx=no fi rm -f ksw_is_osx* ksw_cv_is_osx="$is_osx" ]) is_osx="$ksw_cv_is_osx" if test x"$is_osx" = "xyes"; then AC_DEFINE( [IS_OSX], [], [Define when you run on OSX] ) fi ]) mm3d-1.3.7/README0000644000175000017500000000233310744511356010172 00000000000000This is the README file for Misfit Model 3D Misfit Model 3D is a 3D model editor. It was written and tested on Linux. It is reported to run on other Unix-like operating systems. It also runs on Windows. See INSTALL.WIN32 for Windows-specific instructions. The home page is here: http://www.misfitcode.com/misfitmodel3d/ The help and developer mailing lists (including archives) are here: http://www.misfitcode.com/misfitmodel3d/mailinglist.html Misfit Model 3D requires Qt (3.x) with OpenGL support. See the INSTALL file for details on where to get these packages. This program uses autoconf and automake for building from source. What this means is that if you are lucky you can install this program with these easy steps: ./configure make su [become root] make install Depending on your system configuration, you may have to run "sudo bash" instead of "su" to get a root shell. This will build an 'mm3d' executable and install it in /usr/local/bin. Documentation will be in /usr/local/share/doc/mm3d. On Mac OS X you must run "make mm3d.app" after "make". For more detailed installation instructions, see the INSTALL file. See INSTALL.WIN32 for Windows-specific instructions. mm3d-1.3.7/install-sh0000755000175000017500000002202110744511356011312 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2005-05-14.22 # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" chmodcmd="$chmodprog 0755" chowncmd= chgrpcmd= stripcmd= rmcmd="$rmprog -f" mvcmd="$mvprog" src= dst= dir_arg= dstarg= no_target_directory= usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: -c (ignored) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. --help display this help and exit. --version display version info and exit. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test -n "$1"; do case $1 in -c) shift continue;; -d) dir_arg=true shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; --help) echo "$usage"; exit $?;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -s) stripcmd=$stripprog shift continue;; -t) dstarg=$2 shift shift continue;; -T) no_target_directory=true shift continue;; --version) echo "$0 $scriptversion"; exit $?;; *) # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. test -n "$dir_arg$dstarg" && break # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dstarg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dstarg" shift # fnord fi shift # arg dstarg=$arg done break;; esac done if test -z "$1"; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi for src do # Protect names starting with `-'. case $src in -*) src=./$src ;; esac if test -n "$dir_arg"; then dst=$src src= if test -d "$dst"; then mkdircmd=: chmodcmd= else mkdircmd=$mkdirprog fi else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dstarg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dstarg # Protect names starting with `-'. case $dst in -*) dst=./$dst ;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dstarg: Is a directory" >&2 exit 1 fi dst=$dst/`basename "$src"` fi fi # This sed command emulates the dirname command. dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` # Make sure that the destination directory exists. # Skip lots of stat calls in the usual case. if test ! -d "$dstdir"; then defaultIFS=' ' IFS="${IFS-$defaultIFS}" oIFS=$IFS # Some sh's can't handle IFS=/ for some reason. IFS='%' set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` shift IFS=$oIFS pathcomp= while test $# -ne 0 ; do pathcomp=$pathcomp$1 shift if test ! -d "$pathcomp"; then $mkdirprog "$pathcomp" # mkdir can fail with a `File exist' error in case several # install-sh are creating the directory concurrently. This # is OK. test -d "$pathcomp" || exit fi pathcomp=$pathcomp/ done fi if test -n "$dir_arg"; then $doit $mkdircmd "$dst" \ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } else dstfile=`basename "$dst"` # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 trap '(exit $?); exit' 1 2 13 15 # Copy the file name to the temp name. $doit $cpprog "$src" "$dsttmp" && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && # Now rename the file to the real destination. { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ || { # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { if test -f "$dstdir/$dstfile"; then $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ || { echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 (exit 1); exit 1 } else : fi } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" } } fi || { (exit 1); exit 1; } done # The final little trick to "correctly" pass the exit status to the exit trap. { (exit 0); exit 0 } # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: mm3d-1.3.7/TRANSLATORS0000644000175000017500000000003010744511356011041 00000000000000Slovak Dusan Halicky mm3d-1.3.7/config.guess0000755000175000017500000012626010744511356011640 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. timestamp='2006-07-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; x86:Interix*:[3456]*) echo i586-pc-interix${UNAME_RELEASE} exit ;; EM64T:Interix*:[3456]*) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^CPU/{ s: ::g p }'`" test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout #endif #endif #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' /^LIBC/{ s: ::g p }'`" test x"${LIBC}" != x && { echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit } test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: mm3d-1.3.7/configure0000755000175000017500000127663711025050754011237 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for mm3d 1.3.7. # # Report bugs to . # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell autoconf@gnu.org about your system, echo including any error possibly output before this echo message } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='mm3d' PACKAGE_TARNAME='mm3d' PACKAGE_VERSION='1.3.7' PACKAGE_STRING='mm3d 1.3.7' PACKAGE_BUGREPORT='kevin@misfitcode.com' ac_unique_file="config.h.in" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datarootdir datadir sysconfdir sharedstatedir localstatedir includedir oldincludedir docdir infodir htmldir dvidir pdfdir psdir libdir localedir mandir DEFS ECHO_C ECHO_N ECHO_T LIBS build_alias host_alias target_alias INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CC CFLAGS ac_ct_CC CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE RANLIB CPP GREP EGREP LIBOBJS LUA_CCFLAGS LUA_DIR LUA_LIBS LUALIB_CCFLAGS LUALIB_DIR LUALIB_LIBS DLOPEN_LIBS XMKMF X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS GL_CFLAGS GL_LIBS HAVE_QT4 QT_CXXFLAGS QT_DIR QT_LIBS QT_UIC QT_MOC QT_LRELEASE QGL_LIBS DLOPEN_LIBS BYTEORDER PROFILE CORE_PROFILE LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias host_alias target_alias CXX CXXFLAGS LDFLAGS LIBS CPPFLAGS CCC CC CFLAGS CPP XMKMF' # Initialize some variables set by options. ac_init_help= ac_init_version=false # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid feature name: $ac_feature" >&2 { (exit 1); exit 1; }; } ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` eval enable_$ac_feature=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=\$ac_optarg ;; -without-* | --without-*) ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid package name: $ac_package" >&2 { (exit 1); exit 1; }; } ac_package=`echo $ac_package | sed 's/[-.]/_/g'` eval with_$ac_package=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi # Be sure to have absolute directory names. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { echo "$as_me: error: Working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$0" || $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$0" : 'X\(//\)[^/]' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X"$0" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures mm3d 1.3.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/mm3d] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of mm3d 1.3.7:";; esac cat <<\_ACEOF Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-profile=yes/no/core Specify "yes" or "core" to enable profiling. --enable-debug=yes/no/cov Specify "yes" to enable a debug build. $with_Mesa_help_string Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-lua-dir=DIR DIR is equal to the install prefix of Lua. Header files are in DIR/include, and Library files are in DIR/lib --with-lua-include-dir=DIR Lua header files are in DIR --with-lua-lib-dir=DIR Lua libraries are in DIR --with-lua-lib=LIB Use -lLIB to link with the lua library --with-lualib-dir=DIR DIR is equal to the install prefix of Lualib. Header files are in DIR/include, and Library files are in DIR/lib --with-lualib-include-dir=DIR Lua header files are in DIR --with-lualib-lib-dir=DIR Lua libraries are in DIR --with-lualib-lib=LIB Use -lLIB to link with the lualib library --with-x use the X Window System Prefer the Mesa library over a vendors native OpenGL library (default=yes) --with-Qt-dir=DIR DIR is equal to \$QTDIR if you have followed the installation instructions of Trolltech. Header files are in DIR/include, binary utilities are in DIR/bin and the library is in DIR/lib --with-Qt-include-dir=DIR Qt header files are in DIR --with-Qt-bin-dir=DIR Qt utilities such as moc and uic are in DIR --with-Qt-lib-dir=DIR The Qt library is in DIR Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory CC C compiler command CFLAGS C compiler flags CPP C preprocessor XMKMF Path to xmkmf, Makefile generator for X Window System Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF mm3d configure 1.3.7 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by mm3d $as_me 1.3.7, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && echo "$as_me: caught signal $ac_signal" echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then set x "$CONFIG_SITE" elif test "x$prefix" != xNONE; then set x "$prefix/share/config.site" "$prefix/etc/config.site" else set x "$ac_default_prefix/share/config.site" \ "$ac_default_prefix/etc/config.site" fi shift for ac_site_file do if test -r "$ac_site_file"; then { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { echo "$as_me:$LINENO: loading cache $cache_file" >&5 echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { echo "$as_me:$LINENO: creating cache $cache_file" >&5 echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 echo "$as_me: former value: $ac_old_val" >&2;} { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 echo "$as_me: current value: $ac_new_val" >&2;} ac_cache_corrupted=: fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version="1.9" ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} { (exit 1); exit 1; }; } fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. { echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi done done ;; esac done IFS=$as_save_IFS fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { echo "$as_me:$LINENO: result: $INSTALL" >&5 echo "${ECHO_T}$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { echo "$as_me:$LINENO: checking whether build environment is sane" >&5 echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. echo might interpret backslashes. # By default was `s,x,x', remove it if useless. cat <<\_ACEOF >conftest.sed s/[\\$]/&&/g;s/;s,x,x,$// _ACEOF program_transform_name=`echo $program_transform_name | sed -f conftest.sed` rm -f conftest.sed # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then # We used to keeping the `.' as first argument, in order to # allow $(mkdir_p) to be used without argument. As in # $(mkdir_p) $(somedir) # where $(somedir) is conditionally defined. However this is wrong # for two reasons: # 1. if the package is installed by a user who cannot write `.' # make install will fail, # 2. the above comment should most certainly read # $(mkdir_p) $(DESTDIR)$(somedir) # so it does not work when $(somedir) is undefined and # $(DESTDIR) is not. # To support the latter case, we have to write # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), # so the `.' trick is pointless. mkdir_p='mkdir -p --' else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. for d in ./-p ./--version; do test -d $d && rmdir $d done # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. if test -f "$ac_aux_dir/mkinstalldirs"; then mkdir_p='$(mkinstalldirs)' else mkdir_p='$(install_sh) -d' fi fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_AWK+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { echo "$as_me:$LINENO: result: $AWK" >&5 echo "${ECHO_T}$AWK" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$AWK" && break done { echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } SET_MAKE= else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # test to see if srcdir already configured if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE=mm3d VERSION=1.3.7 cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"$am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { echo "$as_me:$LINENO: result: $STRIP" >&5 echo "${ECHO_T}$STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 echo "${ECHO_T}$ac_ct_STRIP" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers config.h" # Checks for programs. ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { echo "$as_me:$LINENO: result: $CXX" >&5 echo "${ECHO_T}$CXX" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 echo "${ECHO_T}$ac_ct_CXX" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C++ compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5 echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6; } ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # # List of possible output files, starting from the most likely. # The algorithm is not robust to junk in `.', hence go to wildcards (a.*) # only as a last resort. b.out is created by i960 compilers. ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' # # The IRIX 6 linker writes into existing files which may not be # executable, retaining their permissions. Remove them first so a # subsequent execution test works. ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { echo "$as_me:$LINENO: result: $ac_file" >&5 echo "${ECHO_T}$ac_file" >&6; } if test -z "$ac_file"; then echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: C++ compiler cannot create executables See \`config.log' for more details." >&5 echo "$as_me: error: C++ compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5 echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 echo "$as_me: error: cannot run C++ compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi fi fi { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } rm -f a.out a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } { echo "$as_me:$LINENO: result: $cross_compiling" >&5 echo "${ECHO_T}$cross_compiling" >&6; } { echo "$as_me:$LINENO: checking for suffix of executables" >&5 echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest$ac_cv_exeext { echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 echo "${ECHO_T}$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { echo "$as_me:$LINENO: checking for suffix of object files" >&5 echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } if test "${ac_cv_objext+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 echo "${ECHO_T}$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } if test "${ac_cv_cxx_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } GXX=`test $ac_compiler_gnu = yes && echo yes` ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cxx_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CXXFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cxx_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi { echo "$as_me:$LINENO: result: $_am_result" >&5 echo "${ECHO_T}$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CXX" am_compiler_list= { echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { echo "$as_me:$LINENO: result: $CC" >&5 echo "${ECHO_T}$CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 echo "${ECHO_T}$ac_ct_CC" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } # Provide some information about the compiler. echo "$as_me:$LINENO: checking for C compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } GCC=`test $ac_compiler_gnu = yes && echo yes` ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { echo "$as_me:$LINENO: result: none needed" >&5 echo "${ECHO_T}none needed" >&6; } ;; xno) { echo "$as_me:$LINENO: result: unsupported" >&5 echo "${ECHO_T}unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { echo "$as_me:$LINENO: result: $RANLIB" >&5 echo "${ECHO_T}$RANLIB" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 echo "${ECHO_T}$ac_ct_RANLIB" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&5 echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools whose name does not start with the host triplet. If you think this configuration is useful to you, please write to autoconf@gnu.org." >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi { echo "$as_me:$LINENO: checking for profile" >&5 echo $ECHO_N "checking for profile... $ECHO_C" >&6; } # Check whether --enable-profile was given. if test "${enable_profile+set}" = set; then enableval=$enable_profile; fi is_profile=no PROFILE= CORE_PROFILE= if test x"$enable_profile" = xyes; then PROFILE=-pg CORE_PROFILE=-pg is_profile=yes elif test x"$enable_profile" = xcore; then CORE_PROFILE=-pg is_profile="yes (core)" fi cat >>confdefs.h <<\_ACEOF #define PROFILE _ACEOF cat >>confdefs.h <<\_ACEOF #define CORE_PROFILE _ACEOF { echo "$as_me:$LINENO: result: $is_profile" >&5 echo "${ECHO_T}$is_profile" >&6; } { echo "$as_me:$LINENO: checking for debug" >&5 echo $ECHO_N "checking for debug... $ECHO_C" >&6; } # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then enableval=$enable_debug; fi is_debug=no enable_debug_save_COVFLAGS="${COVFLAGS}" enable_debug_save_COVLFLAGS="${COVLFLAGS}" enable_debug_save_CFLAGS="${CFLAGS}" enable_debug_save_CXXFLAGS="${CXXFLAGS}" enable_debug_save_LDFLAGS="${LDFLAGS}" if test x"$enable_debug" = xyes; then COVFLAGS="" COVLFLAGS="" CFLAGS="-g" CXXFLAGS="${CFLAGS}" LDFLAGS="" elif test x"$enable_debug" = xcov; then COVFLAGS="-coverage" COVLFLAGS="-lgcov" CFLAGS="-g" CXXFLAGS="${CFLAGS}" LDFLAGS="" is_debug=coverage else omit_frame= if test x"${CORE_PROFILE}" = "x"; then omit_frame="-fomit-frame-pointer" fi COVFLAGS="" COVLFLAGS="" CFLAGS="-O2 ${omit_frame} -fno-math-errno" CXXFLAGS="${CFLAGS}" LDFLAGS="${omit_frame} -fno-math-errno" fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then if test x"$enable_debug" = xyes; then cat >>confdefs.h <<\_ACEOF #define CODE_DEBUG _ACEOF is_debug=yes fi else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 if test x"$enable_debug" != xyes; then COVFLAGS="${enable_debug_save_COVFLAGS}" COVLFLAGS="${enable_debug_save_COVLFLAGS}" CFLAGS="${enable_debug_save_CFLAGS}" CXXFLAGS="${enable_debug_save_CXXFLAGS}" LDFLAGS="${enable_debug_save_LDFLAGS}" cat >>confdefs.h <<\_ACEOF #define CODE_DEBUG _ACEOF is_debug=yes else COVFLAGS="${enable_debug_save_COVFLAGS}" COVLFLAGS="${enable_debug_save_COVLFLAGS}" CFLAGS="${enable_debug_save_CFLAGS}" CXXFLAGS="${enable_debug_save_CXXFLAGS}" LDFLAGS="${enable_debug_save_LDFLAGS}" fi fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext { echo "$as_me:$LINENO: result: $is_debug" >&5 echo "${ECHO_T}$is_debug" >&6; } # Checks for libraries. # Checks for header files. ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_opendir=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { echo "$as_me:$LINENO: checking for library containing opendir" >&5 echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; } if test "${ac_cv_search_opendir+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_opendir=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 echo "${ECHO_T}$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { echo "$as_me:$LINENO: result: $CPP" >&5 echo "${ECHO_T}$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Extract the first word of "grep ggrep" to use in msg output if test -z "$GREP"; then set dummy grep ggrep; ac_prog_name=$2 if test "${ac_cv_path_GREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS fi GREP="$ac_cv_path_GREP" if test -z "$GREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 echo "${ECHO_T}$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { echo "$as_me:$LINENO: checking for egrep" >&5 echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else # Extract the first word of "egrep" to use in msg output if test -z "$EGREP"; then set dummy egrep; ac_prog_name=$2 if test "${ac_cv_path_EGREP+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS fi EGREP="$ac_cv_path_EGREP" if test -z "$EGREP"; then { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { echo "$as_me:$LINENO: checking for ANSI C header files" >&5 echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } if test "${ac_cv_header_stdc+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 echo "${ECHO_T}$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi { echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_sys_wait_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_WAIT_H 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in limits.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/time.h sys/timeb.h unistd.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ----------------------------------- ## ## Report this to kevin@misfitcode.com ## ## ----------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. { echo "$as_me:$LINENO: checking whether stat file-mode macros are broken" >&5 echo $ECHO_N "checking whether stat file-mode macros are broken... $ECHO_C" >&6; } if test "${ac_cv_header_stat_broken+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if defined S_ISBLK && defined S_IFDIR extern char c1[S_ISBLK (S_IFDIR) ? -1 : 1]; #endif #if defined S_ISBLK && defined S_IFCHR extern char c2[S_ISBLK (S_IFCHR) ? -1 : 1]; #endif #if defined S_ISLNK && defined S_IFREG extern char c3[S_ISLNK (S_IFREG) ? -1 : 1]; #endif #if defined S_ISSOCK && defined S_IFREG extern char c4[S_ISSOCK (S_IFREG) ? -1 : 1]; #endif _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stat_broken=no else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stat_broken=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_header_stat_broken" >&5 echo "${ECHO_T}$ac_cv_header_stat_broken" >&6; } if test $ac_cv_header_stat_broken = yes; then cat >>confdefs.h <<\_ACEOF #define STAT_MACROS_BROKEN 1 _ACEOF fi { echo "$as_me:$LINENO: checking for stdbool.h that conforms to C99" >&5 echo $ECHO_N "checking for stdbool.h that conforms to C99... $ECHO_C" >&6; } if test "${ac_cv_header_stdbool_h+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: true is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) 0.5 == true ? 1 : -1]; bool e = &s; char f[(_Bool) 0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; enum { j = false, k = true, l = false * true, m = true * 256 }; _Bool n[m]; char o[sizeof n == m * sizeof n[0] ? 1 : -1]; char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; # if defined __xlc__ || defined __GNUC__ /* Catch a bug in IBM AIX xlc compiler version 6.0.0.0 reported by James Lemley on 2005-10-05; see http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html This test is not quite right, since xlc is allowed to reject this program, as the initializer for xlcbug is not one of the forms that C requires support for. However, doing the test right would require a runtime test, and that would make cross-compilation harder. Let us hope that IBM fixes the xlc bug, and also adds support for this kind of constant expression. In the meantime, this test will reject xlc, which is OK, since our stdbool.h substitute should suffice. We also test this with GCC, where it should work, to detect more quickly whether someone messes up the test in the future. */ char digs[] = "0123456789"; int xlcbug = 1 / (&(digs + 5)[-2 + (bool) 1] == &digs[4] ? 1 : -1); # endif /* Catch a bug in an HP-UX C compiler. See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html */ _Bool q = true; _Bool *pq = &q; int main () { *pq |= q; *pq |= ! q; /* Refer to every declared value, to avoid compiler optimizations. */ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + !m + !n + !o + !p + !q + !pq); ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdbool_h=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdbool_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_header_stdbool_h" >&5 echo "${ECHO_T}$ac_cv_header_stdbool_h" >&6; } { echo "$as_me:$LINENO: checking for _Bool" >&5 echo $ECHO_N "checking for _Bool... $ECHO_C" >&6; } if test "${ac_cv_type__Bool+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef _Bool ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type__Bool=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type__Bool=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type__Bool" >&5 echo "${ECHO_T}$ac_cv_type__Bool" >&6; } if test $ac_cv_type__Bool = yes; then cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi if test $ac_cv_header_stdbool_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_STDBOOL_H 1 _ACEOF fi { echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; } if test "${ac_cv_c_const+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_const=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 echo "${ECHO_T}$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const _ACEOF fi { echo "$as_me:$LINENO: checking for inline" >&5 echo $ECHO_N "checking for inline... $ECHO_C" >&6; } if test "${ac_cv_c_inline+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_inline=$ac_kw else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5 echo "${ECHO_T}$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac { echo "$as_me:$LINENO: checking for int16_t" >&5 echo $ECHO_N "checking for int16_t... $ECHO_C" >&6; } if test "${ac_cv_c_int16_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_int16_t=no for ac_type in 'int16_t' 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 1) < ($ac_type) (((($ac_type) 1 << (16 - 2)) - 1) * 2 + 2))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 case $ac_type in int16_t) ac_cv_c_int16_t=yes ;; *) ac_cv_c_int16_t=$ac_type ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_int16_t" != no && break done fi { echo "$as_me:$LINENO: result: $ac_cv_c_int16_t" >&5 echo "${ECHO_T}$ac_cv_c_int16_t" >&6; } case $ac_cv_c_int16_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int16_t $ac_cv_c_int16_t _ACEOF ;; esac { echo "$as_me:$LINENO: checking for int32_t" >&5 echo $ECHO_N "checking for int32_t... $ECHO_C" >&6; } if test "${ac_cv_c_int32_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_int32_t=no for ac_type in 'int32_t' 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 1) < ($ac_type) (((($ac_type) 1 << (32 - 2)) - 1) * 2 + 2))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 case $ac_type in int32_t) ac_cv_c_int32_t=yes ;; *) ac_cv_c_int32_t=$ac_type ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_int32_t" != no && break done fi { echo "$as_me:$LINENO: result: $ac_cv_c_int32_t" >&5 echo "${ECHO_T}$ac_cv_c_int32_t" >&6; } case $ac_cv_c_int32_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int32_t $ac_cv_c_int32_t _ACEOF ;; esac { echo "$as_me:$LINENO: checking for int8_t" >&5 echo $ECHO_N "checking for int8_t... $ECHO_C" >&6; } if test "${ac_cv_c_int8_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_int8_t=no for ac_type in 'int8_t' 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(0 < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 1) < ($ac_type) (((($ac_type) 1 << (8 - 2)) - 1) * 2 + 2))]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 case $ac_type in int8_t) ac_cv_c_int8_t=yes ;; *) ac_cv_c_int8_t=$ac_type ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_int8_t" != no && break done fi { echo "$as_me:$LINENO: result: $ac_cv_c_int8_t" >&5 echo "${ECHO_T}$ac_cv_c_int8_t" >&6; } case $ac_cv_c_int8_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int8_t $ac_cv_c_int8_t _ACEOF ;; esac { echo "$as_me:$LINENO: checking for mode_t" >&5 echo $ECHO_N "checking for mode_t... $ECHO_C" >&6; } if test "${ac_cv_type_mode_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef mode_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_mode_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_mode_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5 echo "${ECHO_T}$ac_cv_type_mode_t" >&6; } if test $ac_cv_type_mode_t = yes; then : else cat >>confdefs.h <<_ACEOF #define mode_t int _ACEOF fi { echo "$as_me:$LINENO: checking for size_t" >&5 echo $ECHO_N "checking for size_t... $ECHO_C" >&6; } if test "${ac_cv_type_size_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef size_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_size_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_size_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 echo "${ECHO_T}$ac_cv_type_size_t" >&6; } if test $ac_cv_type_size_t = yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; } if test "${ac_cv_header_time+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_time=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 echo "${ECHO_T}$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF #define TIME_WITH_SYS_TIME 1 _ACEOF fi { echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6; } if test "${ac_cv_struct_tm+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_struct_tm=time.h else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 echo "${ECHO_T}$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then cat >>confdefs.h <<\_ACEOF #define TM_IN_SYS_TIME 1 _ACEOF fi { echo "$as_me:$LINENO: checking for uint16_t" >&5 echo $ECHO_N "checking for uint16_t... $ECHO_C" >&6; } if test "${ac_cv_c_uint16_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_uint16_t=no for ac_type in 'uint16_t' 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(($ac_type) -1 >> (16 - 1) == 1)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then case $ac_type in uint16_t) ac_cv_c_uint16_t=yes ;; *) ac_cv_c_uint16_t=$ac_type ;; esac else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_uint16_t" != no && break done fi { echo "$as_me:$LINENO: result: $ac_cv_c_uint16_t" >&5 echo "${ECHO_T}$ac_cv_c_uint16_t" >&6; } case $ac_cv_c_uint16_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define uint16_t $ac_cv_c_uint16_t _ACEOF ;; esac { echo "$as_me:$LINENO: checking for uint32_t" >&5 echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6; } if test "${ac_cv_c_uint32_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_uint32_t=no for ac_type in 'uint32_t' 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(($ac_type) -1 >> (32 - 1) == 1)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then case $ac_type in uint32_t) ac_cv_c_uint32_t=yes ;; *) ac_cv_c_uint32_t=$ac_type ;; esac else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_uint32_t" != no && break done fi { echo "$as_me:$LINENO: result: $ac_cv_c_uint32_t" >&5 echo "${ECHO_T}$ac_cv_c_uint32_t" >&6; } case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) cat >>confdefs.h <<\_ACEOF #define _UINT32_T 1 _ACEOF cat >>confdefs.h <<_ACEOF #define uint32_t $ac_cv_c_uint32_t _ACEOF ;; esac { echo "$as_me:$LINENO: checking for uint8_t" >&5 echo $ECHO_N "checking for uint8_t... $ECHO_C" >&6; } if test "${ac_cv_c_uint8_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_cv_c_uint8_t=no for ac_type in 'uint8_t' 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !(($ac_type) -1 >> (8 - 1) == 1)]; test_array [0] = 0 ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then case $ac_type in uint8_t) ac_cv_c_uint8_t=yes ;; *) ac_cv_c_uint8_t=$ac_type ;; esac else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_uint8_t" != no && break done fi { echo "$as_me:$LINENO: result: $ac_cv_c_uint8_t" >&5 echo "${ECHO_T}$ac_cv_c_uint8_t" >&6; } case $ac_cv_c_uint8_t in #( no|yes) ;; #( *) cat >>confdefs.h <<\_ACEOF #define _UINT8_T 1 _ACEOF cat >>confdefs.h <<_ACEOF #define uint8_t $ac_cv_c_uint8_t _ACEOF ;; esac # Checks for library functions. { echo "$as_me:$LINENO: checking whether closedir returns void" >&5 echo $ECHO_N "checking whether closedir returns void... $ECHO_C" >&6; } if test "${ac_cv_func_closedir_void+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_closedir_void=yes else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header_dirent> #ifndef __cplusplus int closedir (); #endif int main () { return closedir (opendir (".")) != 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_closedir_void=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_closedir_void=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_closedir_void" >&5 echo "${ECHO_T}$ac_cv_func_closedir_void" >&6; } if test $ac_cv_func_closedir_void = yes; then cat >>confdefs.h <<\_ACEOF #define CLOSEDIR_VOID 1 _ACEOF fi { echo "$as_me:$LINENO: checking for error_at_line" >&5 echo $ECHO_N "checking for error_at_line... $ECHO_C" >&6; } if test "${ac_cv_lib_error_at_line+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { error_at_line (0, 0, "", 0, "an error occurred"); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_error_at_line=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_error_at_line=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_lib_error_at_line" >&5 echo "${ECHO_T}$ac_cv_lib_error_at_line" >&6; } if test $ac_cv_lib_error_at_line = no; then case " $LIBOBJS " in *" error.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS error.$ac_objext" ;; esac fi { echo "$as_me:$LINENO: checking for pid_t" >&5 echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; } if test "${ac_cv_type_pid_t+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default typedef pid_t ac__type_new_; int main () { if ((ac__type_new_ *) 0) return 0; if (sizeof (ac__type_new_)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_pid_t=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_pid_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 echo "${ECHO_T}$ac_cv_type_pid_t" >&6; } if test $ac_cv_type_pid_t = yes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi for ac_header in vfork.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ----------------------------------- ## ## Report this to kevin@misfitcode.com ## ## ----------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in fork vfork do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { echo "$as_me:$LINENO: checking for working fork" >&5 echo $ECHO_N "checking for working fork... $ECHO_C" >&6; } if test "${ac_cv_func_fork_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_fork_works=cross else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_fork_works=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_fork_works" >&5 echo "${ECHO_T}$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { echo "$as_me:$LINENO: checking for working vfork" >&5 echo $ECHO_N "checking for working vfork... $ECHO_C" >&6; } if test "${ac_cv_func_vfork_works+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_vfork_works=cross else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_vfork_works=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_vfork_works" >&5 echo "${ECHO_T}$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { echo "$as_me:$LINENO: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then cat >>confdefs.h <<\_ACEOF #define HAVE_WORKING_VFORK 1 _ACEOF else cat >>confdefs.h <<\_ACEOF #define vfork fork _ACEOF fi if test "x$ac_cv_func_fork_works" = xyes; then cat >>confdefs.h <<\_ACEOF #define HAVE_WORKING_FORK 1 _ACEOF fi { echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5 echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; } if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else rm -f conftest.sym conftest.file echo >conftest.file if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then if test "$cross_compiling" = yes; then ac_cv_func_lstat_dereferences_slashed_symlink=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; /* Linux will dereference the symlink and fail. That is better in the sense that it means we will not have to compile and use the lstat wrapper. */ return lstat ("conftest.sym/", &sbuf) == 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_lstat_dereferences_slashed_symlink=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi else # If the `ln -s' command failed, then we probably don't even # have an lstat function. ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f conftest.sym conftest.file fi { echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && cat >>confdefs.h <<_ACEOF #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 _ACEOF if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then case " $LIBOBJS " in *" lstat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;; esac fi { echo "$as_me:$LINENO: checking whether lstat accepts an empty string" >&5 echo $ECHO_N "checking whether lstat accepts an empty string... $ECHO_C" >&6; } if test "${ac_cv_func_lstat_empty_string_bug+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_lstat_empty_string_bug=yes else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; return lstat ("", &sbuf) == 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_lstat_empty_string_bug=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_lstat_empty_string_bug=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_lstat_empty_string_bug" >&5 echo "${ECHO_T}$ac_cv_func_lstat_empty_string_bug" >&6; } if test $ac_cv_func_lstat_empty_string_bug = yes; then case " $LIBOBJS " in *" lstat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;; esac cat >>confdefs.h <<_ACEOF #define HAVE_LSTAT_EMPTY_STRING_BUG 1 _ACEOF fi { echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5 echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6; } if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else rm -f conftest.sym conftest.file echo >conftest.file if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then if test "$cross_compiling" = yes; then ac_cv_func_lstat_dereferences_slashed_symlink=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; /* Linux will dereference the symlink and fail. That is better in the sense that it means we will not have to compile and use the lstat wrapper. */ return lstat ("conftest.sym/", &sbuf) == 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_lstat_dereferences_slashed_symlink=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi else # If the `ln -s' command failed, then we probably don't even # have an lstat function. ac_cv_func_lstat_dereferences_slashed_symlink=no fi rm -f conftest.sym conftest.file fi { echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && cat >>confdefs.h <<_ACEOF #define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 _ACEOF if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then case " $LIBOBJS " in *" lstat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;; esac fi for ac_header in stdlib.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ----------------------------------- ## ## Report this to kevin@misfitcode.com ## ## ----------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5 echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6; } if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_malloc_0_nonnull=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_malloc_0_nonnull=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5 echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_MALLOC 1 _ACEOF else cat >>confdefs.h <<\_ACEOF #define HAVE_MALLOC 0 _ACEOF case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac cat >>confdefs.h <<\_ACEOF #define malloc rpl_malloc _ACEOF fi { echo "$as_me:$LINENO: checking for working memcmp" >&5 echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6; } if test "${ac_cv_func_memcmp_working+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_memcmp_working=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_memcmp_working=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_memcmp_working=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_memcmp_working" >&5 echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac for ac_header in stdlib.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } else # Is the header compilable? { echo "$as_me:$LINENO: checking $ac_header usability" >&5 echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 echo "${ECHO_T}$ac_header_compiler" >&6; } # Is the header present? { echo "$as_me:$LINENO: checking $ac_header presence" >&5 echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 echo "${ECHO_T}$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ( cat <<\_ASBOX ## ----------------------------------- ## ## Report this to kevin@misfitcode.com ## ## ----------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { echo "$as_me:$LINENO: checking for GNU libc compatible realloc" >&5 echo $ECHO_N "checking for GNU libc compatible realloc... $ECHO_C" >&6; } if test "${ac_cv_func_realloc_0_nonnull+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_realloc_0_nonnull=no else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_realloc_0_nonnull=yes else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_realloc_0_nonnull" >&5 echo "${ECHO_T}$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_REALLOC 1 _ACEOF else cat >>confdefs.h <<\_ACEOF #define HAVE_REALLOC 0 _ACEOF case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac cat >>confdefs.h <<\_ACEOF #define realloc rpl_realloc _ACEOF fi { echo "$as_me:$LINENO: checking return type of signal handlers" >&5 echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; } if test "${ac_cv_type_signal+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_type_signal=int else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 echo "${ECHO_T}$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF { echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5 echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6; } if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test "$cross_compiling" = yes; then ac_cv_func_stat_empty_string_bug=yes else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { struct stat sbuf; return stat ("", &sbuf) == 0; ; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_try") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_cv_func_stat_empty_string_bug=no else echo "$as_me: program exited with status $ac_status" >&5 echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_func_stat_empty_string_bug=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi { echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5 echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6; } if test $ac_cv_func_stat_empty_string_bug = yes; then case " $LIBOBJS " in *" stat.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS stat.$ac_objext" ;; esac cat >>confdefs.h <<_ACEOF #define HAVE_STAT_EMPTY_STRING_BUG 1 _ACEOF fi for ac_func in vprintf do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF { echo "$as_me:$LINENO: checking for _doprnt" >&5 echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6; } if test "${ac_cv_func__doprnt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define _doprnt to an innocuous variant, in case declares _doprnt. For example, HP-UX 11i declares gettimeofday. */ #define _doprnt innocuous__doprnt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char _doprnt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef _doprnt /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char _doprnt (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub__doprnt || defined __stub____doprnt choke me #endif int main () { return _doprnt (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func__doprnt=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func__doprnt=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5 echo "${ECHO_T}$ac_cv_func__doprnt" >&6; } if test $ac_cv_func__doprnt = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_DOPRNT 1 _ACEOF fi fi done for ac_func in ftime getcwd gettimeofday localtime_r memmove memset mkdir pow realpath sqrt strcasecmp strchr strcspn strdup strerror strncasecmp strrchr strspn strstr do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then eval "$as_ac_var=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval echo '${'$as_ac_var'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } if test `eval echo '${'$as_ac_var'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { echo "$as_me:$LINENO: checking for lua" >&5 echo $ECHO_N "checking for lua... $ECHO_C" >&6; } # Check whether --with-lua-dir was given. if test "${with_lua_dir+set}" = set; then withval=$with_lua_dir; fi # Check whether --with-lua-include-dir was given. if test "${with_lua_include_dir+set}" = set; then withval=$with_lua_include_dir; fi # Check whether --with-lua-lib-dir was given. if test "${with_lua_lib_dir+set}" = set; then withval=$with_lua_lib_dir; fi # Check whether --with-lua-lib was given. if test "${with_lua_lib+set}" = set; then withval=$with_lua_lib; fi if test x"$with_lua_dir" = x && test x"$with_lua_include_dir" = x && test x"$with_lua_lib_dir" = x && test x"$with_lua_lib" = x; then # user did not request Lua support, disable it have_lua="disabled" else # "yes" is a bogus option if test x"$with_lua_dir" = xyes; then with_lua_dir= fi if test x"$with_lua_include_dir" = xyes; then with_lua_include_dir= fi if test x"$with_lua_lib_dir" = xyes; then with_lua_lib_dir= fi if test x"$with_lua_lib" = xyes; then with_lua_lib= fi # No lua unless we discover otherwise have_lua=no # Check whether we are requested to link with a specific version if test x"$with_lua_lib" != x; then ksw_lua_lib="$with_lua_lib" fi # Check whether we were supplied with an answer already if test x"$with_lua_dir" != x; then have_lua=yes ksw_lua_dir="$with_lua_dir" ksw_lua_include_dir="$with_lua_dir/include" if test -d "$with_lua_dir/lib64" ; then ksw_lua_lib_dir="$with_lua_dir/lib64" else ksw_lua_lib_dir="$with_lua_dir/lib" fi # Only search for the lib if the user did not define one already if test x"$ksw_lua_lib" = x; then ksw_lua_lib="`ls $ksw_lua_lib_dir/liblua5* 2> /dev/null | sed -n 1p | sed s@$ksw_lua_lib_dir/lib@@ | sed s@[.].*@@`" fi if test x"$ksw_lua_lib" = x; then ksw_lua_lib="`ls $ksw_lua_lib_dir/liblua.* 2> /dev/null | sed -n 1p | sed s@$ksw_lua_lib_dir/lib@@ | sed s@[.].*@@`" fi ksw_lua_LIBS="-L$ksw_lua_lib_dir -l$ksw_lua_lib -lm -ldl" else # Use cached value or do search, starting with suggestions from # the command line if test "${ksw_cv_have_lua+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # We are not given a solution and there is no cached value. ksw_lua_dir= if test x"$ksw_lua_include_dir" = x; then ksw_lua_include_dir="`ls -dr /usr/include/lua.h /usr/local/include/lua.h /usr/include/lua*/lua.h /usr/local/include/lua*/lua.h 2> /dev/null | sed -n 1p | sed s@/lua.h@@`" fi if test x"$ksw_lua_lib" = x; then ksw_lua_lib_dir="`ls -dr /usr/lib64/liblua5* /usr/lib64/liblua.* /usr/local/lib64/liblua5* /usr/local/lib64/liblua.* /usr/lib/liblua5* /usr/lib/liblua.* /usr/local/lib/liblua5* /usr/local/lib/liblua.* 2> /dev/null | sed -n 1p`" ksw_lua_lib="`echo $ksw_lua_lib_dir | sed 's@/.*/@@' `" ksw_lua_lib_dir="`echo $ksw_lua_lib_dir | sed s@/$ksw_lua_lib@@ `" ksw_lua_lib="`echo $ksw_lua_lib | sed s@[.].*@@ | sed s@^lib@@ `" fi if test x"$ksw_lua_lib" != x; then if test x"$ksw_lua_lib_dir" = x; then ksw_lua_LIBS="-l$ksw_lua_lib -lm -ldl" else ksw_lua_LIBS="-L$ksw_lua_lib_dir -l$ksw_lua_lib -lm -ldl" fi # Record where we found lua for the cache. ksw_cv_have_lua="have_lua=yes \ ksw_lua_dir=$ksw_lua_dir \ ksw_lua_include_dir=$ksw_lua_include_dir \ ksw_lua_LIBS=\"$ksw_lua_LIBS\"" fi fi eval "$ksw_cv_have_lua" fi # all $ksw_lua_* are set fi # $have_lua reflects the system status if test x"$have_lua" = xyes; then LUA_CCFLAGS="-I$ksw_lua_include_dir" LUA_DIR="$ksw_lua_dir" LUA_LIBS="$ksw_lua_LIBS" # All variables are defined, report the result cat >>confdefs.h <<\_ACEOF #define HAVE_LUA _ACEOF { echo "$as_me:$LINENO: result: $have_lua: LUA_CCFLAGS=$LUA_CCFLAGS LUA_DIR=$LUA_DIR LUA_LIBS=$LUA_LIBS " >&5 echo "${ECHO_T}$have_lua: LUA_CCFLAGS=$LUA_CCFLAGS LUA_DIR=$LUA_DIR LUA_LIBS=$LUA_LIBS " >&6; } else # lua was not found LUA_CCFLAGS= LUA_DIR= LUA_LIBS= { echo "$as_me:$LINENO: result: $have_lua" >&5 echo "${ECHO_T}$have_lua" >&6; } fi #### Being paranoid: if test x"$have_lua" = xyes; then { echo "$as_me:$LINENO: checking correct functioning of lua installation" >&5 echo $ECHO_N "checking correct functioning of lua installation... $ECHO_C" >&6; } if test "${ksw_cv_lua_test_result+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat > ksw_lua_test.h << EOF EOF cat > ksw_lua_test.c << EOF #include "ksw_lua_test.h" #include #include //#include int main( int argc, char **argv ) { lua_State * L = lua_open(); //luaopen_math( L ); lua_close( L ); return( 0 ); } EOF ksw_cv_lua_test_result="failure" ksw_try_1="$CC $LUA_CCFLAGS $LUA_LIBS -o ksw_lua_test ksw_lua_test.c >/dev/null 2>ksw_lua_test_1.out" { (eval echo "$as_me:$LINENO: \"$ksw_try_1\"") >&5 (eval $ksw_try_1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } ksw_err_1=`grep -v '^ *+' ksw_lua_test_1.out | grep -v "^ksw_lua_test.{$ac_ext}\$"` if test x"$ksw_err_1" != x; then echo "$ksw_err_1" >&5 echo "configure: could not compile:" >&5 cat ksw_lua_test.c >&5 else ksw_cv_lua_test_result="success" fi fi fi { echo "$as_me:$LINENO: result: $ksw_cv_lua_test_result" >&5 echo "${ECHO_T}$ksw_cv_lua_test_result" >&6; }; if test x"$ksw_cv_lua_test_result" = "xfailure"; then { { echo "$as_me:$LINENO: error: Failed to find matching components of a complete lua installation. Try using more options, see ./configure --help." >&5 echo "$as_me: error: Failed to find matching components of a complete lua installation. Try using more options, see ./configure --help." >&2;} { (exit 1); exit 1; }; } fi rm -f ksw_lua_test.h \ ksw_lua_test.c ksw_lua_test.o ksw_lua_test \ ksw_lua_test_1.out if test x"${LUA_LIBS}" != x; then { echo "$as_me:$LINENO: checking for lualib" >&5 echo $ECHO_N "checking for lualib... $ECHO_C" >&6; } # Check whether --with-lualib-dir was given. if test "${with_lualib_dir+set}" = set; then withval=$with_lualib_dir; fi # Check whether --with-lualib-include-dir was given. if test "${with_lualib_include_dir+set}" = set; then withval=$with_lualib_include_dir; fi # Check whether --with-lualib-lib-dir was given. if test "${with_lualib_lib_dir+set}" = set; then withval=$with_lualib_lib_dir; fi # Check whether --with-lualib-lib was given. if test "${with_lualib_lib+set}" = set; then withval=$with_lualib_lib; fi if test x"$with_lualib_dir" = x"no" || test x"$with_lualib_include_dir" = x"no" || test x"$with_lualib_lib_dir" = x"no" || test x"$with_lualib_lib" = x"no"; then # user disabled lualib. Leave cache alone. have_lualib="User disabled lualib." else # "yes" is a bogus option if test x"$with_lualib_dir" = xyes; then with_lualib_dir= fi if test x"$with_lualib_include_dir" = xyes; then with_lualib_include_dir= fi if test x"$with_lualib_lib_dir" = xyes; then with_lualib_lib_dir= fi if test x"$with_lualib_lib" = xyes; then with_lualib_lib= fi # No lualib unless we discover otherwise have_lualib=no # Check whether we are requested to link with a specific version if test x"$with_lualib_lib" != x; then ksw_lualib_lib="$with_lualib_lib" fi # Check whether we were supplied with an answer already if test x"$with_lualib_dir" != x; then have_lualib=yes ksw_lualib_dir="$with_lualib_dir" ksw_lualib_include_dir="$with_lualib_dir/include" if test -d "$with_lualib_dir/lib64" ; then ksw_lualib_lib_dir="$with_lualib_dir/lib64" else ksw_lualib_lib_dir="$with_lualib_dir/lib" fi # Only search for the lib if the user did not define one already if test x"$ksw_lualib_lib" = x; then ksw_lualib_lib="`ls $ksw_lualib_lib_dir/liblualib5* 2> /dev/null | sed -n 1p | sed s@$ksw_lualib_lib_dir/lib@@ | sed s@[.].*@@`" fi if test x"$ksw_lualib_lib" = x; then ksw_lualib_lib="`ls $ksw_lualib_lib_dir/liblualib.* 2> /dev/null | sed -n 1p | sed s@$ksw_lualib_lib_dir/lib@@ | sed s@[.].*@@`" fi ksw_lualib_LIBS="-L$ksw_lualib_lib_dir -l$ksw_lualib_lib" else # Use cached value or do search, starting with suggestions from # the command line if test "${ksw_cv_have_lualib+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # We are not given a solution and there is no cached value. ksw_lualib_dir= if test x"$ksw_lualib_include_dir" = x; then ksw_lualib_include_dir="`ls -dr /usr/include/lualib.h /usr/local/include/lualib.h /usr/include/lua*/lualib.h /usr/local/include/lua*/lualib.h 2> /dev/null | sed -n 1p | sed s@/lualib.h@@`" fi if test x"$ksw_lualib_lib" = x; then ksw_lualib_lib_dir="`ls -dr /usr/lib64/liblualib5* /usr/lib64/liblualib.* /usr/local/lib64/liblualib5* /usr/local/lib64/liblualib.* /usr/lib/liblualib5* /usr/lib/liblualib.* /usr/local/lib/liblualib5* /usr/local/lib/liblualib.* 2> /dev/null | sed -n 1p`" ksw_lualib_lib="`echo $ksw_lualib_lib_dir | sed 's@/.*/@@' `" ksw_lualib_lib_dir="`echo $ksw_lualib_lib_dir | sed s@/$ksw_lualib_lib@@ `" ksw_lualib_lib="`echo $ksw_lualib_lib | sed s@[.].*@@ | sed s@^lib@@ `" fi if test x"$ksw_lualib_lib" != x; then if test x"$ksw_lualib_lib_dir" = x; then ksw_lualib_LIBS="-l$ksw_lualib_lib" else ksw_lualib_LIBS="-L$ksw_lualib_lib_dir -l$ksw_lualib_lib" fi # Record where we found lualib for the cache. ksw_cv_have_lualib="have_lualib=yes \ ksw_lualib_dir=$ksw_lualib_dir \ ksw_lualib_include_dir=$ksw_lualib_include_dir \ ksw_lualib_LIBS=\"$ksw_lualib_LIBS\"" fi fi eval "$ksw_cv_have_lualib" fi # all $ksw_lualib_* are set fi # $have_lualib reflects the system status if test x"$have_lualib" = xyes; then LUALIB_CCFLAGS="-I$ksw_lualib_include_dir" LUALIB_DIR="$ksw_lualib_dir" LUALIB_LIBS="-lm -ldl $LUA_LIBS $ksw_lualib_LIBS" # All variables are defined, report the result cat >>confdefs.h <<\_ACEOF #define HAVE_LUALIB _ACEOF { echo "$as_me:$LINENO: result: $have_lualib: LUALIB_CCFLAGS=$LUALIB_CCFLAGS LUALIB_DIR=$LUALIB_DIR LUALIB_LIBS=$LUALIB_LIBS " >&5 echo "${ECHO_T}$have_lualib: LUALIB_CCFLAGS=$LUALIB_CCFLAGS LUALIB_DIR=$LUALIB_DIR LUALIB_LIBS=$LUALIB_LIBS " >&6; } else # lualib was not found LUALIB_CCFLAGS= LUALIB_DIR= LUALIB_LIBS= { echo "$as_me:$LINENO: result: $have_lualib" >&5 echo "${ECHO_T}$have_lualib" >&6; } fi #### Being paranoid: if test x"$have_lualib" = xyes; then { echo "$as_me:$LINENO: checking correct functioning of lualib installation" >&5 echo $ECHO_N "checking correct functioning of lualib installation... $ECHO_C" >&6; } if test "${ksw_cv_lualib_test_result+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat > ksw_lualib_test.h << EOF EOF cat > ksw_lualib_test.c << EOF #include "ksw_lualib_test.h" #include #include #include int main( int argc, char **argv ) { lua_State * L = lua_open(); luaopen_math( L ); lua_close( L ); return( 0 ); } EOF ksw_cv_lualib_test_result="failure" ksw_try_1="$CC $LUALIB_CCFLAGS $LUALIB_LIBS -o ksw_lualib_test ksw_lualib_test.c >/dev/null 2>ksw_lualib_test_1.out" { (eval echo "$as_me:$LINENO: \"$ksw_try_1\"") >&5 (eval $ksw_try_1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } ksw_err_1=`grep -v '^ *+' ksw_lualib_test_1.out | grep -v "^ksw_lualib_test.{$ac_ext}\$"` if test x"$ksw_err_1" != x; then echo "$ksw_err_1" >&5 echo "configure: could not compile:" >&5 cat ksw_lualib_test.c >&5 else ksw_cv_lualib_test_result="success" fi fi fi { echo "$as_me:$LINENO: result: $ksw_cv_lualib_test_result" >&5 echo "${ECHO_T}$ksw_cv_lualib_test_result" >&6; }; if test x"$ksw_cv_lualib_test_result" = "xfailure"; then { { echo "$as_me:$LINENO: error: Failed to find matching components of a complete lualib installation. Try using more options, see ./configure --help." >&5 echo "$as_me: error: Failed to find matching components of a complete lualib installation. Try using more options, see ./configure --help." >&2;} { (exit 1); exit 1; }; } fi rm -f ksw_lualib_test.h \ ksw_lualib_test.c ksw_lualib_test.o ksw_lualib_test \ ksw_lualib_test_1.out fi { echo "$as_me:$LINENO: checking for OS X" >&5 echo $ECHO_N "checking for OS X... $ECHO_C" >&6; } if test "${ksw_cv_is_osx+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else if test -e /System/Library/Frameworks/Carbon.framework; then is_osx=yes else is_osx=no fi rm -f ksw_is_osx* ksw_cv_is_osx="$is_osx" fi { echo "$as_me:$LINENO: result: $ksw_cv_is_osx" >&5 echo "${ECHO_T}$ksw_cv_is_osx" >&6; } is_osx="$ksw_cv_is_osx" if test x"$is_osx" = "xyes"; then cat >>confdefs.h <<\_ACEOF #define IS_OSX _ACEOF fi { echo "$as_me:$LINENO: checking for dlopen" >&5 echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } if test "${ksw_cv_have_dlopen+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else DLOPEN_save_LIBS="$LIBS" if test x"$is_osx" = xyes; then DLOPEN_LIBS="-ldl" else DLOPEN_LIBS="-ldl -rdynamic" fi LIBS="$DLOPEN_save_LIBS $DLOPEN_LIBS" cat > ksw_dlopen_test.c << EOF #include #include int main( int argc, char * argv ) { dlopen( "filename", 0 ); return 0; } EOF if ${CC} -o ksw_dlopen_test ksw_dlopen_test.c $LIBS 2> /dev/null > /dev/null; then have_dlopen=yes else DLOPEN_LIBS="-ldl -Wl,export-dynamic" LIBS="$DLOPEN_save_LIBS $DLOPEN_LIBS" if ${CC} -o ksw_dlopen_test ksw_dlopen_test.c $LIBS 2> /dev/null > /dev/null; then have_dlopen=yes else have_dlopen=no DLOPEN_LIBS= fi fi rm -f ksw_dlopen_test ksw_dlopen_test.c LIBS="$DLOPEN_save_LIBS" ksw_cv_DLOPEN_LIBS="$DLOPEN_LIBS" ksw_cv_have_dlopen="$have_dlopen" fi { echo "$as_me:$LINENO: result: $ksw_cv_have_dlopen" >&5 echo "${ECHO_T}$ksw_cv_have_dlopen" >&6; } DLOPEN_LIBS="$ksw_cv_DLOPEN_LIBS" have_dlopen="$ksw_cv_have_dlopen" if test x"$have_dlopen" = "xyes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_DLOPEN _ACEOF fi { echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&6; } # Check whether --with-x was given. if test "${with_x+set}" = set; then withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5 echo "$as_me: error: Cannot use X directory names containing '" >&2;} { (exit 1); exit 1; }; };; #( *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /lib) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # We can compile using X headers with no special include directory. ac_x_includes= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS=$ac_save_LIBS for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no";; #( *) # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { echo "$as_me:$LINENO: result: $have_x" >&5 echo "${ECHO_T}$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; } fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. cat >>confdefs.h <<\_ACEOF #define X_DISPLAY_MISSING 1 _ACEOF X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . { echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6; } ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" ac_xsave_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } X_LIBS="$X_LIBS -R$x_libraries" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 LIBS="$ac_xsave_LIBS -R $x_libraries" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } X_LIBS="$X_LIBS -R $x_libraries" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: result: neither works" >&5 echo "${ECHO_T}neither works" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext ac_c_werror_flag=$ac_xsave_c_werror_flag LIBS=$ac_xsave_LIBS fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char XOpenDisplay (); int main () { return XOpenDisplay (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then : else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6; } if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dnet_dnet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dnet_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6; } if test $ac_cv_lib_dnet_dnet_ntoa = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6; } if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_dnet_stub_dnet_ntoa=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. { echo "$as_me:$LINENO: checking for gethostbyname" >&5 echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6; } if test "${ac_cv_func_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gethostbyname to an innocuous variant, in case declares gethostbyname. For example, HP-UX 11i declares gettimeofday. */ #define gethostbyname innocuous_gethostbyname /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gethostbyname (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef gethostbyname /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_gethostbyname || defined __stub___gethostbyname choke me #endif int main () { return gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6; } if test $ac_cv_func_gethostbyname = no; then { echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6; } if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_nsl_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6; } if test $ac_cv_lib_nsl_gethostbyname = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6; } if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_bsd_gethostbyname=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_bsd_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6; } if test $ac_cv_lib_bsd_gethostbyname = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. { echo "$as_me:$LINENO: checking for connect" >&5 echo $ECHO_N "checking for connect... $ECHO_C" >&6; } if test "${ac_cv_func_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define connect to an innocuous variant, in case declares connect. For example, HP-UX 11i declares gettimeofday. */ #define connect innocuous_connect /* System header to define __stub macros and hopefully few prototypes, which can conflict with char connect (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef connect /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_connect || defined __stub___connect choke me #endif int main () { return connect (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 echo "${ECHO_T}$ac_cv_func_connect" >&6; } if test $ac_cv_func_connect = no; then { echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6; } if test "${ac_cv_lib_socket_connect+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_socket_connect=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6; } if test $ac_cv_lib_socket_connect = yes; then X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. { echo "$as_me:$LINENO: checking for remove" >&5 echo $ECHO_N "checking for remove... $ECHO_C" >&6; } if test "${ac_cv_func_remove+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define remove to an innocuous variant, in case declares remove. For example, HP-UX 11i declares gettimeofday. */ #define remove innocuous_remove /* System header to define __stub macros and hopefully few prototypes, which can conflict with char remove (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef remove /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char remove (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_remove || defined __stub___remove choke me #endif int main () { return remove (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_remove=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_remove=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 echo "${ECHO_T}$ac_cv_func_remove" >&6; } if test $ac_cv_func_remove = no; then { echo "$as_me:$LINENO: checking for remove in -lposix" >&5 echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6; } if test "${ac_cv_lib_posix_remove+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char remove (); int main () { return remove (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_posix_remove=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_posix_remove=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6; } if test $ac_cv_lib_posix_remove = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. { echo "$as_me:$LINENO: checking for shmat" >&5 echo $ECHO_N "checking for shmat... $ECHO_C" >&6; } if test "${ac_cv_func_shmat+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define shmat to an innocuous variant, in case declares shmat. For example, HP-UX 11i declares gettimeofday. */ #define shmat innocuous_shmat /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shmat (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shmat /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shmat (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_shmat || defined __stub___shmat choke me #endif int main () { return shmat (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_func_shmat=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shmat=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 echo "${ECHO_T}$ac_cv_func_shmat" >&6; } if test $ac_cv_func_shmat = no; then { echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6; } if test "${ac_cv_lib_ipc_shmat+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shmat (); int main () { return shmat (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ipc_shmat=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ipc_shmat=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6; } if test $ac_cv_lib_ipc_shmat = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry { echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6; } if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char IceConnectionNumber (); int main () { return IceConnectionNumber (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_lib_ICE_IceConnectionNumber=yes else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6; } if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi { echo "$as_me:$LINENO: checking for OpenGL" >&5 echo $ECHO_N "checking for OpenGL... $ECHO_C" >&6; } if test "${mdl_cv_have_OpenGL+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # Check whether --with---with-Mesa was given. if test "${with___with_Mesa+set}" = set; then withval=$with___with_Mesa; with_Mesa_help_string fi # Check whether --enable-Mesa was given. if test "${enable_Mesa+set}" = set; then enableval=$enable_Mesa; use_Mesa=$enableval else use_Mesa=yes fi if test x"$use_Mesa" = xyes; then GL_search_list="MesaGL GL" GLU_search_list="MesaGLU GLU" GLX_search_list="MesaGLX GLX" else GL_search_list="GL MesaGL" GLU_search_list="GLU MesaGLU" GLX_search_list="GLX MesaGLX" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test x"$is_osx" = xyes; then GL_CFLAGS="-framework OpenGL -framework AGL" GL_LIBS="-framework OpenGL -framework AGL" else if test x"$no_x" != xyes; then GL_CFLAGS="$X_CFLAGS" GL_X_LIBS="$X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" fi fi GL_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$GL_CFLAGS" GL_save_LIBS="$LIBS" LIBS="$GL_X_LIBS" # Save the "AC_MSG_RESULT file descriptor" to FD 8. exec 8>&6 # Temporarily turn off AC_MSG_RESULT so that the user gets pretty # messages. exec 6>/dev/null { echo "$as_me:$LINENO: checking for library containing glAccum" >&5 echo $ECHO_N "checking for library containing glAccum... $ECHO_C" >&6; } if test "${ac_cv_search_glAccum+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glAccum (); int main () { return glAccum (); ; return 0; } _ACEOF for ac_lib in '' $GL_search_list; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_glAccum=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_glAccum+set}" = set; then break fi done if test "${ac_cv_search_glAccum+set}" = set; then : else ac_cv_search_glAccum=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_glAccum" >&5 echo "${ECHO_T}$ac_cv_search_glAccum" >&6; } ac_res=$ac_cv_search_glAccum if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" have_GL=yes else have_GL=no fi { echo "$as_me:$LINENO: checking for library containing gluBeginCurve" >&5 echo $ECHO_N "checking for library containing gluBeginCurve... $ECHO_C" >&6; } if test "${ac_cv_search_gluBeginCurve+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gluBeginCurve (); int main () { return gluBeginCurve (); ; return 0; } _ACEOF for ac_lib in '' $GLU_search_list; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_gluBeginCurve=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_gluBeginCurve+set}" = set; then break fi done if test "${ac_cv_search_gluBeginCurve+set}" = set; then : else ac_cv_search_gluBeginCurve=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_gluBeginCurve" >&5 echo "${ECHO_T}$ac_cv_search_gluBeginCurve" >&6; } ac_res=$ac_cv_search_gluBeginCurve if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" have_GLU=yes else have_GLU=no fi { echo "$as_me:$LINENO: checking for library containing glXChooseVisual" >&5 echo $ECHO_N "checking for library containing glXChooseVisual... $ECHO_C" >&6; } if test "${ac_cv_search_glXChooseVisual+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glXChooseVisual (); int main () { return glXChooseVisual (); ; return 0; } _ACEOF for ac_lib in '' $GLX_search_list; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_glXChooseVisual=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_glXChooseVisual+set}" = set; then break fi done if test "${ac_cv_search_glXChooseVisual+set}" = set; then : else ac_cv_search_glXChooseVisual=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_glXChooseVisual" >&5 echo "${ECHO_T}$ac_cv_search_glXChooseVisual" >&6; } ac_res=$ac_cv_search_glXChooseVisual if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" have_GLX=yes else have_GLX=no fi { echo "$as_me:$LINENO: checking for library containing glutInit" >&5 echo $ECHO_N "checking for library containing glutInit... $ECHO_C" >&6; } if test "${ac_cv_search_glutInit+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char glutInit (); int main () { return glutInit (); ; return 0; } _ACEOF for ac_lib in '' glut; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then ac_cv_search_glutInit=$ac_res else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_glutInit+set}" = set; then break fi done if test "${ac_cv_search_glutInit+set}" = set; then : else ac_cv_search_glutInit=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { echo "$as_me:$LINENO: result: $ac_cv_search_glutInit" >&5 echo "${ECHO_T}$ac_cv_search_glutInit" >&6; } ac_res=$ac_cv_search_glutInit if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" have_glut=yes else have_glut=no fi # Restore pretty messages. exec 6>&8 if test -n "$LIBS"; then mdl_cv_have_OpenGL=yes GL_LIBS="$LIBS" else mdl_cv_have_OpenGL=no GL_CFLAGS= fi GL_X_LIBS= LIBS="$GL_save_LIBS" CPPFLAGS="$GL_save_CPPFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu mdl_cv_GL_CFLAGS="$GL_CFLAGS" mdl_cv_GL_LIBS="$GL_LIBS" mdl_cv_have_GL="$have_GL" mdl_cv_have_GLU="$have_GLU" mdl_cv_have_GLX="$have_GLX" mdl_cv_have_glut="$have_glut" fi { echo "$as_me:$LINENO: result: $mdl_cv_have_OpenGL" >&5 echo "${ECHO_T}$mdl_cv_have_OpenGL" >&6; } GL_CFLAGS="$mdl_cv_GL_CFLAGS" GL_LIBS="$mdl_cv_GL_LIBS" have_GL="$mdl_cv_have_GL" have_GLU="$mdl_cv_have_GLU" have_GLX="$mdl_cv_have_GLX" have_glut="$mdl_cv_have_glut" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { echo "$as_me:$LINENO: checking for Qt" >&5 echo $ECHO_N "checking for Qt... $ECHO_C" >&6; } QT_XLIBS="$X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" if test x"$no_x" = xyes; then QT_XLIBS="" fi if test x"$is_osx" = xyes; then QT_XLIBS="" fi # Check whether --with-Qt-dir was given. if test "${with_Qt_dir+set}" = set; then withval=$with_Qt_dir; fi # Check whether --with-Qt-include-dir was given. if test "${with_Qt_include_dir+set}" = set; then withval=$with_Qt_include_dir; fi # Check whether --with-Qt-bin-dir was given. if test "${with_Qt_bin_dir+set}" = set; then withval=$with_Qt_bin_dir; fi # Check whether --with-Qt-lib-dir was given. if test "${with_Qt_lib_dir+set}" = set; then withval=$with_Qt_lib_dir; fi bnv_is_qt4=no bnv_qt4_libs="-lQtCore -lQtGui -lQtOpenGL -lQtNetwork" if test x"$with_Qt_dir" = x"no" || test x"$with_Qt_include_dir" = x"no" || test x"$with_Qt_bin_dir" = x"no" || test x"$with_Qt_lib_dir" = x"no"; then # user disabled Qt. Leave cache alone. have_qt="User disabled Qt." else # "yes" is a bogus option if test x"$with_Qt_dir" = xyes; then with_Qt_dir= fi if test x"$with_Qt_include_dir" = xyes; then with_Qt_include_dir= fi if test x"$with_Qt_bin_dir" = xyes; then with_Qt_bin_dir= fi if test x"$with_Qt_lib_dir" = xyes; then with_Qt_lib_dir= fi # No Qt unless we discover otherwise have_qt=no # Check whether we were supplied with an answer already if test x"$with_Qt_dir" != x; then have_qt=yes bnv_qt_dir="$with_Qt_dir" bnv_qt_include_dir="$with_Qt_dir/include" bnv_qt_bin_dir="$with_Qt_dir/bin" if test -d "$with_Qt_dir/lib64" ; then bnv_qt_lib_dir="$with_Qt_dir/lib64" else bnv_qt_lib_dir="$with_Qt_dir/lib" fi bnv_qt_LIBS="-L$bnv_qt_lib_dir $bnv_qt4_libs $QT_XLIBS " else # Use cached value or do search, starting with suggestions from # the command line if test "${bnv_cv_have_qt+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else # We are not given a solution and there is no cached value. bnv_qt_dir=NO bnv_qt_include_dir=NO bnv_qt_lib_dir=NO ## Binary utilities ## if test x"$with_Qt_bin_dir" != x; then bnv_qt_bin_dir=$with_Qt_bin_dir fi ## Look for header files ## if test x"$with_Qt_include_dir" != x; then bnv_qt_include_dir="$with_Qt_include_dir" else # The following header file is expected to define QT_VERSION. # Look for the header file in a standard set of common directories. qt_direct_test_header=qglobal.h bnv_include_path_list=" /usr/include `ls -dr /usr/include/qt* 2>/dev/null` `ls -dr /usr/lib/qt*/include 2>/dev/null` `ls -dr /usr/local/qt*/include 2>/dev/null` `ls -dr /opt/sfw/include 2>/dev/null` `ls -dr /opt/qt*/include 2>/dev/null` `ls -dr /usr/qt*/include 2>/dev/null` `ls -dr /usr/qt/*/include 2>/dev/null` `ls -dr /usr/include/qt/* 2>/dev/null` " for bnv_dir in $bnv_include_path_list; do if test -r "$bnv_dir/Qt/$qt_direct_test_header"; then bnv_dirs="$bnv_dirs $bnv_dir" fi done # Now look for the newest in this list bnv_prev_ver=0 for bnv_dir in $bnv_dirs; do if test -r "$bnv_dir/Qt/$qt_direct_test_header"; then bnv_this_ver=`egrep -w '#define QT_VERSION' $bnv_dir/Qt/$qt_direct_test_header | sed s/'#define QT_VERSION'//` if expr $bnv_this_ver '>' $bnv_prev_ver > /dev/null; then bnv_is_qt4=yes bnv_qt_include_dir=$bnv_dir bnv_prev_ver=$bnv_this_ver fi fi done fi # Are these headers located in a traditional Trolltech installation? # That would be $bnv_qt_include_dir stripped from its last element: bnv_found_traditional=no bnv_possible_qt_dir=`dirname $bnv_qt_include_dir` if test -x $bnv_possible_qt_dir/bin/moc-qt4 && ls $bnv_possible_qt_dir/lib/libQtCore* 1> /dev/null 2> /dev/null; then bnv_found_traditional=yes elif test -x $bnv_possible_qt_dir/bin/moc && ls $bnv_possible_qt_dir/lib/libQtCore.* 1> /dev/null 2> /dev/null; then bnv_found_traditional=yes fi if test x"$bnv_found_traditional" = xyes; then # Then the rest is a piece of cake bnv_qt_dir=$bnv_possible_qt_dir bnv_qt_bin_dir="$bnv_qt_dir/bin" if test -d "$bnv_qt_dir/lib64" ; then bnv_qt_lib_dir="$bnv_qt_dir/lib64" else bnv_qt_lib_dir="$bnv_qt_dir/lib" fi bnv_qt_LIBS="-L$bnv_qt_lib_dir $bnv_qt4_libs $QT_XLIBS" fi if test $bnv_found_traditional = no; then # There is no valid definition for $QTDIR as Trolltech likes to see it bnv_qt_dir= ## Look for Qt library ## if test x"$with_Qt_lib_dir" != x; then bnv_qt_lib_dir="$with_Qt_lib_dir" bnv_qt_LIBS="-L$bnv_qt_lib_dir $bnv_qt4_libs $QT_XLIBS" else # Normally, when there is no traditional Trolltech installation, # the library is installed in a place where the linker finds it # automatically. qt_direct_test_header=qapplication.h qt_direct_test_main=" int argc; char ** argv; QApplication app(argc,argv); " # See if we find the library without any special options. # Don't add top $LIBS permanently yet bnv_save_LIBS="$LIBS" bnv_save_CXXFLAGS="$CXXFLAGS" CXXFLAGS="-I$bnv_qt_include_dir" LIBS="$bnv_qt4_libs $QT_XLIBS" bnv_qt_LIBS="$LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$qt_direct_test_header> int main () { $qt_direct_test_main ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && $as_test_x conftest$ac_exeext; then # Succes. # We can link with no special library directory. bnv_qt_lib_dir= else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # That did not work. Maybe a library version I don't know about? # Look for some Qt lib in a standard set of common directories. bnv_dir_list=" `echo $bnv_qt_includes | sed ss/includess` /lib /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /opt/lib64 /opt/lib `ls -dr /usr/lib/qt* 2>/dev/null` `ls -dr /usr/local/qt* 2>/dev/null` `ls -dr /opt/qt* 2>/dev/null` " for bnv_dir in $bnv_dir_list; do if ls $bnv_dir/libQtCore* > /dev/null 2> /dev/null ; then bnv_qt_lib_dir="$bnv_dir" break fi done # Try with that one LIBS="$bnv_qt4_libs $QT_XLIBS" fi rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test x"$bnv_qt_lib_dir" != x; then bnv_qt_LIBS="-L$bnv_qt_lib_dir $LIBS" else bnv_qt_LIBS="$LIBS" fi LIBS="$bnv_save_LIBS" CXXFLAGS="$bnv_save_CXXFLAGS" fi fi if test "$bnv_qt_dir" = NO || test "$bnv_qt_include_dir" = NO || test "$bnv_qt_lib_dir" = NO; then # Problem with finding complete Qt. Cache the known absence of Qt. bnv_cv_have_qt="have_qt=no" else # Record where we found Qt for the cache. bnv_cv_have_qt="have_qt=yes \ bnv_qt_dir=$bnv_qt_dir \ bnv_qt_include_dir=$bnv_qt_include_dir \ bnv_qt_bin_dir=$bnv_qt_bin_dir \ bnv_is_qt4=$bnv_is_qt4 \ bnv_qt_LIBS=\"$bnv_qt_LIBS\"" fi fi eval "$bnv_cv_have_qt" fi # all $bnv_qt_* are set fi # $have_qt reflects the system status if test x"$have_qt" = xyes; then QT_CXXFLAGS="-I$bnv_qt_include_dir" QT_DIR="$bnv_qt_dir" QT_LIBS="$bnv_qt_LIBS" if test x"$bnv_qt_bin_dir" != x; then # We were told where to look for the utilities? # UIC detection if test -x "$bnv_qt_bin_dir/uic-qt4"; then QT_UIC="$bnv_qt_bin_dir/uic-qt4" elif test -x "$bnv_qt_bin_dir/qt4-uic"; then QT_UIC="$bnv_qt_bin_dir/qt4-uic" elif test -x "$bnv_qt_bin_dir/uic"; then QT_UIC="$bnv_qt_bin_dir/uic" fi # MOC detection if test -x "$bnv_qt_bin_dir/moc-qt4"; then QT_MOC="$bnv_qt_bin_dir/moc-qt4" elif test -x "$bnv_qt_bin_dir/qt4-moc"; then QT_MOC="$bnv_qt_bin_dir/qt4-moc" elif test -x "$bnv_qt_bin_dir/moc"; then QT_MOC="$bnv_qt_bin_dir/moc" fi # LRELEASE detection if test -x "$bnv_qt_bin_dir/lrelease-qt4"; then QT_LRELEASE="$bnv_qt_bin_dir/lrelease-qt4" elif test -x "$bnv_qt_bin_dir/qt4-lrelease"; then QT_LRELEASE="$bnv_qt_bin_dir/qt4-lrelease" elif test -x "$bnv_qt_bin_dir/lrelease"; then QT_LRELEASE="$bnv_qt_bin_dir/lrelease" fi elif test x"$bnv_qt_dir" != x; then # If bnv_qt_dir is defined, utilities are expected to be in the # bin subdirectory # UIC detection if test -x "$bnv_qt_dir/bin/uic-qt4"; then QT_UIC="$bnv_qt_dir/bin/uic-qt4" elif test -x "$bnv_qt_dir/bin/qt4-uic"; then QT_UIC="$bnv_qt_dir/bin/qt4-uic" elif test -x "$bnv_qt_dir/bin/uic"; then QT_UIC="$bnv_qt_dir/bin/uic" fi # MOC detection if test -x "$bnv_qt_dir/bin/moc-qt4"; then QT_MOC="$bnv_qt_dir/bin/moc-qt4" elif test -x "$bnv_qt_dir/bin/qt4-moc"; then QT_MOC="$bnv_qt_dir/bin/qt4-moc" elif test -x "$bnv_qt_dir/bin/moc"; then QT_MOC="$bnv_qt_dir/bin/moc" fi # LRELEASE detection if test -x "$bnv_qt_dir/bin/lrelease-qt4"; then QT_LRELEASE="$bnv_qt_dir/bin/lrelease-qt4" elif test -x "$bnv_qt_dir/bin/qt4-lrelease"; then QT_LRELEASE="$bnv_qt_dir/bin/qt4-lrelease" elif test -x "$bnv_qt_dir/bin/lrelease"; then QT_LRELEASE="$bnv_qt_dir/bin/lrelease" fi fi # If binaries are still not set, try $PATH if test x"$QT_UIC" = x; then # UIC detection if test `which uic-qt4 2> /dev/null`; then QT_UIC=`which uic-qt4` elif test `which qt4-uic 2> /dev/null`; then QT_UIC=`which qt4-uic` elif test `which uic 2> /dev/null`; then QT_UIC=`which uic` fi fi if test x"$QT_MOC" = x; then # MOC detection if test `which moc-qt4 2> /dev/null`; then QT_MOC=`which moc-qt4` elif test `which qt4-moc 2> /dev/null`; then QT_MOC=`which qt4-moc` elif test `which moc 2> /dev/null`; then QT_MOC=`which moc` fi fi if test x"$QT_LRELEASE" = x; then # LRELEASE detection if test `which lrelease-qt4 2> /dev/null`; then QT_LRELEASE=`which lrelease-qt4` elif test `which qt4-lrelease 2> /dev/null`; then QT_LRELEASE=`which qt4-lrelease` elif test `which lrelease 2> /dev/null`; then QT_LRELEASE=`which lrelease` fi fi # All variables are defined, report the result { echo "$as_me:$LINENO: result: $have_qt: QT_CXXFLAGS=$QT_CXXFLAGS QT_DIR=$QT_DIR QT_LIBS=$QT_LIBS QT_UIC=$QT_UIC QT_MOC=$QT_MOC QT_LRELEASE=$QT_LRELEASE" >&5 echo "${ECHO_T}$have_qt: QT_CXXFLAGS=$QT_CXXFLAGS QT_DIR=$QT_DIR QT_LIBS=$QT_LIBS QT_UIC=$QT_UIC QT_MOC=$QT_MOC QT_LRELEASE=$QT_LRELEASE" >&6; } else # Qt was not found QT_CXXFLAGS= QT_DIR= QT_LIBS= QT_UIC= QT_MOC= QT_LRELEASE= { echo "$as_me:$LINENO: result: $have_qt" >&5 echo "${ECHO_T}$have_qt" >&6; } fi if test x"$bnv_is_qt4" = xyes; then HAVE_QT4=1 cat >>confdefs.h <<\_ACEOF #define HAVE_QT4 _ACEOF fi #### Being paranoid: if test x"$have_qt" = xyes; then { echo "$as_me:$LINENO: checking correct functioning of Qt installation" >&5 echo $ECHO_N "checking correct functioning of Qt installation... $ECHO_C" >&6; } if test "${bnv_cv_qt_test_result+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat > bnv_qt_test.h << EOF #include class Test : public QObject { Q_OBJECT public: Test() {} ~Test() {} public slots: void receive() {} signals: void send(); }; EOF cat > bnv_qt_main.$ac_ext << EOF #include "bnv_qt_test.h" #include int main( int argc, char **argv ) { QApplication app( argc, argv ); Test t; QObject::connect( &t, SIGNAL(send()), &t, SLOT(receive()) ); } EOF bnv_cv_qt_test_result="failure" bnv_try_1="$QT_MOC bnv_qt_test.h -o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_1.out" { (eval echo "$as_me:$LINENO: \"$bnv_try_1\"") >&5 (eval $bnv_try_1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } bnv_err_1=`grep -v '^ *+' bnv_qt_test_1.out | grep -v "^bnv_qt_test.h\$"` if test x"$bnv_err_1" != x; then echo "$bnv_err_1" >&5 echo "configure: could not run $QT_MOC on:" >&5 cat bnv_qt_test.h >&5 else bnv_try_2="$CXX $QT_CXXFLAGS -c $CXXFLAGS -Wno-non-virtual-dtor -o moc_bnv_qt_test.o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_2.out" { (eval echo "$as_me:$LINENO: \"$bnv_try_2\"") >&5 (eval $bnv_try_2) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } bnv_err_2=`grep -v '^ *+' bnv_qt_test_2.out | grep -v "^bnv_qt_test.{$ac_ext}\$"` if test x"$bnv_err_2" != x; then echo "$bnv_err_2" >&5 echo "configure: could not compile:" >&5 cat bnv_qt_test.$ac_ext >&5 else bnv_try_3="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o bnv_qt_main.o bnv_qt_main.$ac_ext >/dev/null 2>bnv_qt_test_3.out" { (eval echo "$as_me:$LINENO: \"$bnv_try_3\"") >&5 (eval $bnv_try_3) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } bnv_err_3=`grep -v '^ *+' bnv_qt_test_3.out | grep -v "^bnv_qt_main.{$ac_ext}\$"` if test x"$bnv_err_3" != x; then echo "$bnv_err_3" >&5 echo "configure: could not compile:" >&5 cat bnv_qt_main.$ac_ext >&5 else bnv_try_4="$CXX $QT_LIBS $LIBS -o bnv_qt_main bnv_qt_main.o moc_bnv_qt_test.o >/dev/null 2>bnv_qt_test_4.out" { (eval echo "$as_me:$LINENO: \"$bnv_try_4\"") >&5 (eval $bnv_try_4) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } bnv_err_4=`grep -v '^ *+' bnv_qt_test_4.out` if test x"$bnv_err_4" != x; then echo "$bnv_err_4" >&5 else bnv_cv_qt_test_result="success" fi fi fi fi fi { echo "$as_me:$LINENO: result: $bnv_cv_qt_test_result" >&5 echo "${ECHO_T}$bnv_cv_qt_test_result" >&6; }; if test x"$bnv_cv_qt_test_result" = "xfailure"; then { { echo "$as_me:$LINENO: error: Failed to find matching components of a complete Qt installation. Try using more options, see ./configure --help." >&5 echo "$as_me: error: Failed to find matching components of a complete Qt installation. Try using more options, see ./configure --help." >&2;} { (exit 1); exit 1; }; } fi rm -f bnv_qt_test.h moc_bnv_qt_test.$ac_ext moc_bnv_qt_test.o \ bnv_qt_main.$ac_ext bnv_qt_main.o bnv_qt_main \ bnv_qt_test_1.out bnv_qt_test_2.out bnv_qt_test_3.out bnv_qt_test_4.out fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { echo "$as_me:$LINENO: checking Qt OpenGL" >&5 echo $ECHO_N "checking Qt OpenGL... $ECHO_C" >&6; } if test "${ksw_cv_qgl_test_result+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat > ksw_qgl_test.${ac_ext} << EOF #include #include #include int main( int argc, char ** argv ) { QApplication app( argc, argv ); QGLWidget w; w.show(); return app.exec(); } EOF ksw_cv_qgl_test_result="failure" ksw_try_1="$CXX $GL_CFLAGS $GL_LIBS $QT_CXXFLAGS $QT_LIBS -o ksw_qgl_test ksw_qgl_test.${ac_ext} >/dev/null 2>ksw_qgl_test_1.out" { (eval echo "$as_me:$LINENO: \"$ksw_try_1\"") >&5 (eval $ksw_try_1) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } ksw_err_1=`grep -v '^ *+' ksw_qgl_test_1.out | grep -v "^ksw_qgl_test.{$ac_ext}\$"` if test x"$ksw_err_1" != x; then ksw_try_2="$CXX $GL_CFLAGS $GL_LIBS $QT_CXXFLAGS $QT_LIBS -lqglviewer -o ksw_qgl_test ksw_qgl_test.${ac_ext} >/dev/null 2>ksw_qgl_test_2.out" { (eval echo "$as_me:$LINENO: \"$ksw_try_2\"") >&5 (eval $ksw_try_2) 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } ksw_err_2=`grep -v '^ *+' ksw_qgl_test_2.out | grep -v "^ksw_qgl_test.{$ac_ext}\$"` if test x"$ksw_err_2" != x; then echo "$ksw_err_2" >&5 echo "configure: could not compile:" >&5 cat ksw_qgl_test.${ac_ext} >&5 else ksw_cv_qgl_test_result="success" QGL_LIBS=-lqglviewer fi else ksw_cv_qgl_test_result="success" QGL_LIBS= fi fi { echo "$as_me:$LINENO: result: $ksw_cv_qgl_test_result" >&5 echo "${ECHO_T}$ksw_cv_qgl_test_result" >&6; }; if test x"$ksw_cv_qgl_test_result" = "xfailure"; then { { echo "$as_me:$LINENO: error: Failed to link Qt with OpenGL support." >&5 echo "$as_me: error: Failed to link Qt with OpenGL support." >&2;} { (exit 1); exit 1; }; } fi rm -f ksw_qgl_test.h \ ksw_qgl_test.${ac_ext} ksw_qgl_test.o ksw_qgl_test \ ksw_qgl_test_1.out ksw_qgl_test_2.out ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { echo "$as_me:$LINENO: checking for x11 fonts" >&5 echo $ECHO_N "checking for x11 fonts... $ECHO_C" >&6; } if test "${ksw_cv_have_x11font+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat > ksw_have_x11font_test.c << EOF #include #include int main( int argc, char * argv ) { glXUseXFont( 0, 0, 0, 0 ); return 0; } EOF if ${CC} -c ksw_have_x11font_test.c 2> /dev/null > /dev/null; then have_x11font=yes else have_x11font=no fi rm -f ksw_have_x11font* ksw_cv_have_x11font="$have_x11font" fi { echo "$as_me:$LINENO: result: $ksw_cv_have_x11font" >&5 echo "${ECHO_T}$ksw_cv_have_x11font" >&6; } have_x11font="$ksw_cv_have_x11font" if test x"$have_x11font" = "xyes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_XFONT _ACEOF fi { echo "$as_me:$LINENO: checking for gettimeofday" >&5 echo $ECHO_N "checking for gettimeofday... $ECHO_C" >&6; } if test "${ksw_cv_have_gettimeofday+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else cat > ksw_have_gettimeofday_test.c << EOF #include #include int main( int argc, char * argv ) { struct timeval tv; gettimeofday( &tv, NULL ); return 0; } EOF if ${CC} -c ksw_have_gettimeofday_test.c 2> /dev/null > /dev/null; then have_gettimeofday=yes else have_gettimeofday=no fi rm -f ksw_have_gettimeofday* ksw_cv_have_gettimeofday="$have_gettimeofday" fi { echo "$as_me:$LINENO: result: $ksw_cv_have_gettimeofday" >&5 echo "${ECHO_T}$ksw_cv_have_gettimeofday" >&6; } have_gettimeofday="$ksw_cv_have_gettimeofday" if test x"$have_gettimeofday" = "xyes"; then cat >>confdefs.h <<\_ACEOF #define HAVE_GETTIMEOFDAY _ACEOF fi if test x"$prefix" != xNONE; then cat >>confdefs.h <<_ACEOF #define PREFIX "$prefix" _ACEOF else cat >>confdefs.h <<_ACEOF #define PREFIX "$ac_default_prefix" _ACEOF fi if test x"${QT_LIBS}" = x; then echo "" { { echo "$as_me:$LINENO: error: Qt is required. If you have Qt installed see --help for more options" >&5 echo "$as_me: error: Qt is required. If you have Qt installed see --help for more options" >&2;} { (exit 1); exit 1; }; } echo "" fi if test x"$have_GLU" != xyes; then echo "" { { echo "$as_me:$LINENO: error: OpenGL (with GLU) is required." >&5 echo "$as_me: error: OpenGL (with GLU) is required." >&2;} { (exit 1); exit 1; }; } echo "" fi if test x"${ksw_cv_qgl_test_result}" = xfailure; then echo "" { { echo "$as_me:$LINENO: error: Qt with OpenGL is required." >&5 echo "$as_me: error: Qt with OpenGL is required." >&2;} { (exit 1); exit 1; }; } echo "" fi ac_config_files="$ac_config_files Makefile src/Makefile src/libmm3d/Makefile src/mm3dcore/Makefile src/depui/Makefile src/qtui/Makefile src/implui/Makefile src/tools/Makefile src/commands/Makefile src/pixmap/Makefile plugins/Makefile man/Makefile i18n/Makefile desktop/Makefile doc/Makefile doc/html/Makefile doc/html/olh_images/Makefile doc/html/olh_images/tools/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { echo "$as_me:$LINENO: updating cache $cache_file" >&5 echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then echo "#! /bin/sh" >conf$$.sh echo "exit 0" >>conf$$.sh chmod +x conf$$.sh if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then PATH_SEPARATOR=';' else PATH_SEPARATOR=: fi rm -f conf$$.sh fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) as_nl=' ' IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. for as_var in \ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ LC_TELEPHONE LC_TIME do if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then eval $as_var=C; export $as_var else ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var fi done # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir fi echo >conf$$.file if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by mm3d $as_me 1.3.7, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTIONS] [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ mm3d config.status 1.3.7 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2006 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If no file are specified by the user, then we need to provide default # value. By we need to know if files were specified by the user. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift CONFIG_FILES="$CONFIG_FILES $ac_optarg" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header { echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; };; --help | --hel | -h ) echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF if \$ac_cs_recheck; then echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 CONFIG_SHELL=$SHELL export CONFIG_SHELL exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/libmm3d/Makefile") CONFIG_FILES="$CONFIG_FILES src/libmm3d/Makefile" ;; "src/mm3dcore/Makefile") CONFIG_FILES="$CONFIG_FILES src/mm3dcore/Makefile" ;; "src/depui/Makefile") CONFIG_FILES="$CONFIG_FILES src/depui/Makefile" ;; "src/qtui/Makefile") CONFIG_FILES="$CONFIG_FILES src/qtui/Makefile" ;; "src/implui/Makefile") CONFIG_FILES="$CONFIG_FILES src/implui/Makefile" ;; "src/tools/Makefile") CONFIG_FILES="$CONFIG_FILES src/tools/Makefile" ;; "src/commands/Makefile") CONFIG_FILES="$CONFIG_FILES src/commands/Makefile" ;; "src/pixmap/Makefile") CONFIG_FILES="$CONFIG_FILES src/pixmap/Makefile" ;; "plugins/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/Makefile" ;; "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;; "i18n/Makefile") CONFIG_FILES="$CONFIG_FILES i18n/Makefile" ;; "desktop/Makefile") CONFIG_FILES="$CONFIG_FILES desktop/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/html/Makefile") CONFIG_FILES="$CONFIG_FILES doc/html/Makefile" ;; "doc/html/olh_images/Makefile") CONFIG_FILES="$CONFIG_FILES doc/html/olh_images/Makefile" ;; "doc/html/olh_images/tools/Makefile") CONFIG_FILES="$CONFIG_FILES doc/html/olh_images/tools/Makefile" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { echo "$me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # # Set up the sed scripts for CONFIG_FILES section. # # No need to generate the scripts if there are no CONFIG_FILES. # This happens for instance when ./config.status config.h if test -n "$CONFIG_FILES"; then _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF SHELL!$SHELL$ac_delim PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim PACKAGE_NAME!$PACKAGE_NAME$ac_delim PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim PACKAGE_STRING!$PACKAGE_STRING$ac_delim PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim exec_prefix!$exec_prefix$ac_delim prefix!$prefix$ac_delim program_transform_name!$program_transform_name$ac_delim bindir!$bindir$ac_delim sbindir!$sbindir$ac_delim libexecdir!$libexecdir$ac_delim datarootdir!$datarootdir$ac_delim datadir!$datadir$ac_delim sysconfdir!$sysconfdir$ac_delim sharedstatedir!$sharedstatedir$ac_delim localstatedir!$localstatedir$ac_delim includedir!$includedir$ac_delim oldincludedir!$oldincludedir$ac_delim docdir!$docdir$ac_delim infodir!$infodir$ac_delim htmldir!$htmldir$ac_delim dvidir!$dvidir$ac_delim pdfdir!$pdfdir$ac_delim psdir!$psdir$ac_delim libdir!$libdir$ac_delim localedir!$localedir$ac_delim mandir!$mandir$ac_delim DEFS!$DEFS$ac_delim ECHO_C!$ECHO_C$ac_delim ECHO_N!$ECHO_N$ac_delim ECHO_T!$ECHO_T$ac_delim LIBS!$LIBS$ac_delim build_alias!$build_alias$ac_delim host_alias!$host_alias$ac_delim target_alias!$target_alias$ac_delim INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim INSTALL_DATA!$INSTALL_DATA$ac_delim CYGPATH_W!$CYGPATH_W$ac_delim PACKAGE!$PACKAGE$ac_delim VERSION!$VERSION$ac_delim ACLOCAL!$ACLOCAL$ac_delim AUTOCONF!$AUTOCONF$ac_delim AUTOMAKE!$AUTOMAKE$ac_delim AUTOHEADER!$AUTOHEADER$ac_delim MAKEINFO!$MAKEINFO$ac_delim install_sh!$install_sh$ac_delim STRIP!$STRIP$ac_delim INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim mkdir_p!$mkdir_p$ac_delim AWK!$AWK$ac_delim SET_MAKE!$SET_MAKE$ac_delim am__leading_dot!$am__leading_dot$ac_delim AMTAR!$AMTAR$ac_delim am__tar!$am__tar$ac_delim am__untar!$am__untar$ac_delim CXX!$CXX$ac_delim CXXFLAGS!$CXXFLAGS$ac_delim LDFLAGS!$LDFLAGS$ac_delim CPPFLAGS!$CPPFLAGS$ac_delim ac_ct_CXX!$ac_ct_CXX$ac_delim EXEEXT!$EXEEXT$ac_delim OBJEXT!$OBJEXT$ac_delim DEPDIR!$DEPDIR$ac_delim am__include!$am__include$ac_delim am__quote!$am__quote$ac_delim AMDEP_TRUE!$AMDEP_TRUE$ac_delim AMDEP_FALSE!$AMDEP_FALSE$ac_delim AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim CXXDEPMODE!$CXXDEPMODE$ac_delim am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim CC!$CC$ac_delim CFLAGS!$CFLAGS$ac_delim ac_ct_CC!$ac_ct_CC$ac_delim CCDEPMODE!$CCDEPMODE$ac_delim am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim RANLIB!$RANLIB$ac_delim CPP!$CPP$ac_delim GREP!$GREP$ac_delim EGREP!$EGREP$ac_delim LIBOBJS!$LIBOBJS$ac_delim LUA_CCFLAGS!$LUA_CCFLAGS$ac_delim LUA_DIR!$LUA_DIR$ac_delim LUA_LIBS!$LUA_LIBS$ac_delim LUALIB_CCFLAGS!$LUALIB_CCFLAGS$ac_delim LUALIB_DIR!$LUALIB_DIR$ac_delim LUALIB_LIBS!$LUALIB_LIBS$ac_delim DLOPEN_LIBS!$DLOPEN_LIBS$ac_delim XMKMF!$XMKMF$ac_delim X_CFLAGS!$X_CFLAGS$ac_delim X_PRE_LIBS!$X_PRE_LIBS$ac_delim X_LIBS!$X_LIBS$ac_delim X_EXTRA_LIBS!$X_EXTRA_LIBS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF CEOF$ac_eof _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF GL_CFLAGS!$GL_CFLAGS$ac_delim GL_LIBS!$GL_LIBS$ac_delim HAVE_QT4!$HAVE_QT4$ac_delim QT_CXXFLAGS!$QT_CXXFLAGS$ac_delim QT_DIR!$QT_DIR$ac_delim QT_LIBS!$QT_LIBS$ac_delim QT_UIC!$QT_UIC$ac_delim QT_MOC!$QT_MOC$ac_delim QT_LRELEASE!$QT_LRELEASE$ac_delim QGL_LIBS!$QGL_LIBS$ac_delim DLOPEN_LIBS!$DLOPEN_LIBS$ac_delim BYTEORDER!$BYTEORDER$ac_delim PROFILE!$PROFILE$ac_delim CORE_PROFILE!$CORE_PROFILE$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 15; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` if test -n "$ac_eof"; then ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` ac_eof=`expr $ac_eof + 1` fi cat >>$CONFIG_STATUS <<_ACEOF cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof /@[a-zA-Z_][a-zA-Z_0-9]*@/!b end _ACEOF sed ' s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g s/^/s,@/; s/!/@,|#_!!_#|/ :n t n s/'"$ac_delim"'$/,g/; t s/$/\\/; p N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n ' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF :end s/|#_!!_#|//g CEOF$ac_eof _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF fi # test -n "$CONFIG_FILES" for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 echo "$as_me: error: Invalid tag $ac_tag." >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac ac_file_inputs="$ac_file_inputs $ac_f" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input="Generated from "`IFS=: echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { echo "$as_me:$LINENO: creating $ac_file" >&5 echo "$as_me: creating $ac_file" >&6;} fi case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin";; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= case `sed -n '/datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' $ac_file_inputs` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF sed "$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s&@configure_input@&$configure_input&;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t $ac_datarootdir_hack " $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out"; rm -f "$tmp/out";; *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; esac ;; :H) # # CONFIG_HEADER # _ACEOF # Transform confdefs.h into a sed script `conftest.defines', that # substitutes the proper values into config.h.in to produce config.h. rm -f conftest.defines conftest.tail # First, append a space to every undef/define line, to ease matching. echo 's/$/ /' >conftest.defines # Then, protect against being on the right side of a sed subst, or in # an unquoted here document, in config.status. If some macros were # called several times there might be several #defines for the same # symbol, which is useless. But do not sort them, since the last # AC_DEFINE must be honored. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* # These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where # NAME is the cpp macro being defined, VALUE is the value it is being given. # PARAMS is the parameter list in the macro definition--in most cases, it's # just an empty string. ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*' ac_dB='\\)[ (].*,\\1define\\2' ac_dC=' ' ac_dD=' ,' uniq confdefs.h | sed -n ' t rset :rset s/^[ ]*#[ ]*define[ ][ ]*// t ok d :ok s/[\\&,]/\\&/g s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p ' >>conftest.defines # Remove the space that was appended to ease matching. # Then replace #undef with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. # (The regexp can be short, since the line contains either #define or #undef.) echo 's/ $// s,^[ #]*u.*,/* & */,' >>conftest.defines # Break up conftest.defines: ac_max_sed_lines=50 # First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1" # Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2" # Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1" # et cetera. ac_in='$ac_file_inputs' ac_out='"$tmp/out1"' ac_nxt='"$tmp/out2"' while : do # Write a here document: cat >>$CONFIG_STATUS <<_ACEOF # First, check the format of the line: cat >"\$tmp/defines.sed" <<\\CEOF /^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def /^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def b :def _ACEOF sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS echo 'CEOF sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail grep . conftest.tail >/dev/null || break rm -f conftest.defines mv conftest.tail conftest.defines done rm -f conftest.defines conftest.tail echo "ac_result=$ac_in" >>$CONFIG_STATUS cat >>$CONFIG_STATUS <<\_ACEOF if test x"$ac_file" != x-; then echo "/* $configure_input */" >"$tmp/config.h" cat "$ac_result" >>"$tmp/config.h" if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 echo "$as_me: $ac_file is unchanged" >&6;} else rm -f $ac_file mv "$tmp/config.h" $ac_file fi else echo "/* $configure_input */" cat "$ac_result" fi rm -f "$tmp/out12" # Compute $ac_file's index in $config_headers. _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $ac_file | $ac_file:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $ac_file" >`$as_dirname -- $ac_file || $as_expr X$ac_file : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X$ac_file : 'X\(//\)[^/]' \| \ X$ac_file : 'X\(//\)$' \| \ X$ac_file : 'X\(/\)' \| . 2>/dev/null || echo X$ac_file | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # So let's grep whole file. if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir=$dirpart/$fdir case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi if test x"${have_dlopen}" != xyes; then echo "" echo "Warning: dlopen was not detected. You can contiue with the" echo "install, but plugins will not work." echo "" fi mm3d-1.3.7/TODO0000644000175000017500000001036111000471710007763 00000000000000For 1.4: Bump mm3dfilter version Update plugin docs to point to User's 1.4 plugin directory Testing: Compare frame animations (propEqual and equiv) Implement MD3 filter test FIXMEs Centralize the FunctionCaller For 1.6: Resample animation Change animation playback speed Bone Joints Interactive influence weight adjustment IK Considerations Fix relative paths when saving in a different directory Export/Import MM3D Geometry Materials Skeleton Animations Texture Projections Types Icosahedron Gradient textures Only list supported image formats in animation capture export Integrate libmisfit Make middle mouse button scroll zoom in on point under the mouse Delay normal calculation when manipulating a large number of vertices Fix MM3D data size problem (assume size instead of using read size) Embedded textures Implement embedded textures Extract embedded textures to external files Allow double-sided polygons Attract near/far Position decal 2D/3D Curve: linear/sin/log/quad Later: Warn user if some model properties will not be saved in specified format Format options: Model format-specific dialog box (like Save dialog) Must save in that format to get dialog Dialog always available (tabbed for each format?) Save format-specific options in MM3D format Options dialog can encode/decode Prompt at save time Only prompt for options on first save or on "Save As" Meta data context panel For meta data of any primitive Coloring on texture paint Adjust texture coordinates on turn edge? Adjust texture coordinates on split edge? On user path input, always replace backslashes with slashes MD3 Custom export dialog to select groups, tags, and animations Handle missing/out-of-order animations more sanely Center viewport on mouse position Point meta data? Check flipping on 3DS texture coordinates Import heightmap as "terrain" Transformation - scale translation keyframes MM3D Unsupported data Load/save unknown type info UI for unknown type info Cylinder/Sphere Mapping Projection Window Show test pattern Move pole on sphere? Move pole on icosahedron? Bone Joints Multiple root joints Allowing reparenting and re-rooting of bone structure will invalidate keyframe animations have to deal with parents defined after children Allow setting of other OpenGL options? Commands Increase poly count to smooth (see blender?) Text Force save of a specific type Report OpenGL status (supported options) Unified drawing code Consider using glVertexPointer, glInterleavedArrays, or other draw optimization Import/Export .X (DirectX) Lightwave Export 3DS AC3D Wings MD5 ASE Direct primitive property edit Scale UV Normal Tools Align to line Align to plane Select Select Edge Click repeatedly to cycle through faces under the mouse (Ctrl-click?) Sculpt tool (surface that pushes selected vertices) More complete plugin window Allow enabling/disabling of plugins Allow plugin initialization order changes? Apply heightmap to selected faces Attempt to correct bad data in mm3d load, and allow user to attempt to continue Probably never: Finish MenuManager Hooks for add/remove model elements (for plugins) Scripting Make copy of model Script directories grafted into menu Script debugger Selection Select All Created (or all of type) Bilinear autoscale on non-power-of-two textures Animation Add frame relative Tools Ruler Chamfered primitives Custom lighting Save viewport as JPEG Import/Export FBX SMD Gamestudio MDL Renderman Blender Maya ASCII Raw OpenGL (Triangle Vertices, Normals, and Texture Coords) Texture coordinates Map group should preserve aspect ratio mm3d-1.3.7/mm3d.reg0000755000175000017500000000045210744511356010654 00000000000000Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Misfit Code\Misfit Model 3D] "INSTDIR"="C:\\Program Files\\Misfit Model 3D" mm3d-1.3.7/config.sub0000755000175000017500000007746010744511356011312 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, # Inc. timestamp='2006-09-20' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | mt \ | msp430 \ | nios | nios2 \ | ns16k | ns32k \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | score \ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | xstormy16-* | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16c) basic_machine=cr16c-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: mm3d-1.3.7/desktop/0000777000175000017500000000000011031450307011032 500000000000000mm3d-1.3.7/desktop/Makefile.in0000644000175000017500000002135611025503555013031 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = desktop DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BYTEORDER = @BYTEORDER@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_PROFILE = @CORE_PROFILE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLOPEN_LIBS = @DLOPEN_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ HAVE_QT4 = @HAVE_QT4@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ LUALIB_CCFLAGS = @LUALIB_CCFLAGS@ LUALIB_DIR = @LUALIB_DIR@ LUALIB_LIBS = @LUALIB_LIBS@ LUA_CCFLAGS = @LUA_CCFLAGS@ LUA_DIR = @LUA_DIR@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PROFILE = @PROFILE@ QGL_LIBS = @QGL_LIBS@ QT_CXXFLAGS = @QT_CXXFLAGS@ QT_DIR = @QT_DIR@ QT_LIBS = @QT_LIBS@ QT_LRELEASE = @QT_LRELEASE@ QT_MOC = @QT_MOC@ QT_UIC = @QT_UIC@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ EXTRA_DIST = \ mm3d.desktop \ x-mm3d.desktop \ mm3d.xpm \ mm3d-16.xpm all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu desktop/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu desktop/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-info-am all: install: $(INSTALL) -d $(DESTDIR)$(datadir)/applications/ $(INSTALL) -d $(DESTDIR)$(datadir)/mimelnk/application/ $(INSTALL) -d $(DESTDIR)$(datadir)/pixmaps/ ${INSTALL} -m 0644 mm3d.desktop $(DESTDIR)$(datadir)/applications/ ${INSTALL} -m 0644 x-mm3d.desktop $(DESTDIR)$(datadir)/mimelnk/application/ ${INSTALL} -m 0644 *.xpm $(DESTDIR)$(datadir)/pixmaps/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mm3d-1.3.7/desktop/mm3d.xpm0000644000175000017500000001331610744511356012354 00000000000000/* XPM */ static char * mm3dlogo_32x32_xpm[] = { "32 32 225 2", " c None", ". c #0000FA", "+ c #0000F9", "@ c #000061", "# c #8E0000", "$ c #0000DE", "% c #00005E", "& c #8C0000", "* c #9A0000", "= c #A60000", "- c #AE0000", "; c #B30000", "> c #B50000", ", c #B20000", "' c #AC0000", ") c #A20000", "! c #990000", "~ c #0000D0", "{ c #980000", "] c #AB0000", "^ c #B90000", "/ c #C20000", "( c #C80000", "_ c #CD0000", ": c #CA0000", "< c #C70000", "[ c #C10000", "} c #A50000", "| c #910000", "1 c #0000BF", "2 c #890000", "3 c #C30000", "4 c #CE0000", "5 c #D40000", "6 c #D80000", "7 c #DC0000", "8 c #D90000", "9 c #D30000", "0 c #CC0000", "a c #B10000", "b c #960000", "c c #0000A4", "d c #680014", "e c #9F0000", "f c #B60000", "g c #C50000", "h c #D00000", "i c #DF0000", "j c #E40000", "k c #E70000", "l c #E60000", "m c #C60000", "n c #000091", "o c #220043", "p c #970000", "q c #D10000", "r c #E10000", "s c #EB0000", "t c #ED0000", "u c #EE0000", "v c #E20000", "w c #DB0000", "x c #B00000", "y c #000083", "z c #070058", "A c #7A000B", "B c #C00000", "C c #EA0000", "D c #F00000", "E c #F30000", "F c #F40000", "G c #F10000", "H c #BD0000", "I c #000066", "J c #350034", "K c #9B0000", "L c #B40000", "M c #DE0000", "N c #F70000", "O c #F80000", "P c #F50000", "Q c #E80000", "R c #E00000", "S c #D70000", "T c #AF0000", "U c #0000EC", "V c #600017", "W c #A40000", "X c #BC0000", "Y c #E90000", "Z c #EF0000", "` c #F90000", " . c #FA0000", ".. c #CF0000", "+. c #BA0000", "@. c #0000E2", "#. c #05005A", "$. c #830004", "%. c #AD0000", "&. c #DD0000", "*. c #EC0000", "=. c #F60000", "-. c #FB0000", ";. c #F20000", ">. c #BF0000", ",. c #0000C4", "'. c #22003D", "). c #920000", "!. c #D20000", "~. c #FC0000", "{. c #FD0000", "]. c #0000B1", "^. c #1E0044", "/. c #C40000", "(. c #A70000", "_. c #1D0044", ":. c #E50000", "<. c #000088", "[. c #8D0000", "}. c #E30000", "|. c #000073", "1. c #13004D", "2. c #850000", "3. c #D60000", "4. c #D50000", "5. c #0000F8", "6. c #000068", "7. c #01005D", "8. c #66000F", "9. c #9E0000", "0. c #DA0000", "a. c #0000E7", "b. c #39002C", "c. c #C90000", "d. c #B80000", "e. c #A00000", "f. c #7F0000", "g. c #0000D7", "h. c #11004D", "i. c #7E0001", "j. c #CB0000", "k. c #BB0000", "l. c #3D0026", "m. c #8A0000", "n. c #A30000", "o. c #7B0000", "p. c #0000AB", "q. c #0300A5", "r. c #5B002F", "s. c #900000", "t. c #000099", "u. c #0000BC", "v. c #0B00DD", "w. c #600020", "x. c #8B0000", "y. c #BE0000", "z. c #7D0000", "A. c #000086", "B. c #0000CF", "C. c #0600E6", "D. c #4F003C", "E. c #820000", "F. c #930000", "G. c #6C000E", "H. c #00006E", "I. c #0000ED", "J. c #0300F0", "K. c #29008A", "L. c #620018", "M. c #950000", "N. c #61002D", "O. c #2A0092", "P. c #0500CC", "Q. c #0000F1", "R. c #000064", "S. c #00005D", "T. c #00005F", "U. c #0000E0", "V. c #0000F5", "W. c #0100F6", "X. c #1E00A9", "Y. c #3A0068", "Z. c #50003E", "`. c #56003E", " + c #51003E", ".+ c #3C006A", "++ c #1A00B7", "@+ c #0100F8", "#+ c #0000E3", "$+ c #00005A", "%+ c #000054", "&+ c #00004D", "*+ c #000047", "=+ c #000041", "-+ c #00003C", ";+ c #000039", ">+ c #000048", ",+ c #0000A0", "'+ c #0000C1", ")+ c #0000E1", "!+ c #0000F4", "~+ c #0000F3", "{+ c #0000DD", "]+ c #000098", "^+ c #000078", "/+ c #000058", "(+ c #00003F", "_+ c #000046", ":+ c #000060", "<+ c #00007F", "[+ c #00009F", "}+ c #0000C3", "|+ c #0000E5", "1+ c #0000D2", "2+ c #0000B3", "3+ c #000093", "4+ c #00005C", "5+ c #000082", "6+ c #0000E9", "7+ c #0000C8", "8+ c #0000A8", "9+ c #000069", "0+ c #00003A", "a+ c #00007D", "b+ c #000089", " ", " . + @ # ", " . $ % % & * = - ; > , ' ) ! ", " . ~ % % % { ] ^ / ( _ _ : < [ > } | ", " . 1 % % % % 2 ) > 3 4 5 6 7 7 7 8 9 0 [ a b ", " . . c % % % % % d e f g h 6 i j k l l j i 8 9 m , { ", " . . n % % % % o p , g q 8 r k s t u t s k v w q 3 x ", " . . y % % % z A ' B h 8 v C t D E F E G u C v 8 4 H ) ", " . . I % % % J K L < 5 M l t G F N O N P E D Q R S < T | ", " . U @ % % % V W X 0 6 v Y Z F N ` .` N P G s j 7 ..+.* ", " . @.% % % #.$.%./ h &.l *.G =.` .-.-.` =.;.t l &.q >.W ", " . ,.% % % '.)., g !.i k t E O .-.~.{.-.N E u Q &.q [ = ", " . ].% % % ^.).a /.!.M l *.;.N ` -.~.{.-.O F D Y &.!.[ (. ", " . c % % % _.| T 3 q 7 :.s G P N ` . .` =.;.u k &.!.[ (. ", " . . <.% % % _.[.' [ ..8 }.C u ;.P N O N =.E Z C }.8 4 X W ", " . . |.% % % 1.2.(.X 0 3.r Q *.Z E P P F E D *.l i 4.< L p ", " . 5.6.% % % 7.8.9.> /.h w }.k s Z ;.G D Z t k r 0...>.] 2 ", " . a.% % % % % b.| %.X c.9 w r :.Q s s C Y l r w 5 < d.e.f. ", " . g.% % % % % h.i.e , / j.9 0.M r }.j }.r M 8 !.c.k.] # ", " . ,.% % % % % % l.m.n.> [ c.q 3.8 w 7 7 8 3.h < H %.b o. ", " . p.% % % % % % q.r.s.n.a X /.: _ h q h _ c.3 k.- * o. ", " . . t.% % % % % % u.v.w.x.9.' ; ^ y.[ [ B y.^ a (.b z. ", " . . A.% % % % % % B.. C.D.E.F.9.= ' x T %.] n.* 2 G. ", " . . H.% % % % % % I.. . J.K.L.f.[.).M.b M.[.E.N.O.P. ", " . Q.R.% % % % S.T.U.V.. . . W.X.Y.Z.`.`. +.+++@+. ", " . #+$+%+&+*+=+-+;+;+>+R.y ,+'+)+!+. . . . . . . . ", " . ~+{+u.]+^+/+(+;+;+;+;+;+;+;+;+_+:+<+[+}+|+V.. + ", " . . . . . . . U 1+2+3+|.&+;+;+;+;+;+;+;+;+;+>+4+5+ ", " . . . . . . . . . + 6+7+8+<.9+*+;+;+;+;+0+%+ ", " . . . . . . . . . !+#+}+,+a+$+ ", " . . . . . . . . . b+ ", " . . . "}; mm3d-1.3.7/desktop/mm3d.desktop0000644000175000017500000000044310744511356013216 00000000000000[Desktop Entry] Encoding=UTF-8 Type=Application Exec=mm3d %U Icon=mm3d DocPath=mm3d/index.html GenericName=3D Modeler Comment=3D modeling program Terminal=false Name=mm3d MimeType=application/x-mm3d Categories=Qt;Application;Graphics; X-AppInstall-Package=mm3d X-AppInstall-Section=universe mm3d-1.3.7/desktop/mm3d-16.xpm0000644000175000017500000000512710744511356012601 00000000000000/* XPM */ static char * mm3d_16_xpm[] = { "16 16 126 2", " c None", ". c #0000FA", "+ c #0000E8", "@ c #00005E", "# c #9A0000", "$ c #AF0000", "% c #BE0000", "& c #C00000", "* c #B60000", "= c #A60000", "- c #0000D6", "; c #340039", "> c #A00000", ", c #C30000", "' c #D60000", ") c #E00000", "! c #E10000", "~ c #DC0000", "{ c #CE0000", "] c #B00000", "^ c #0000C2", "/ c #02005C", "( c #780014", "_ c #C20000", ": c #D90000", "< c #E80000", "[ c #EF0000", "} c #F00000", "| c #EC0000", "1 c #E20000", "2 c #CF0000", "3 c #0000AB", "4 c #250042", "5 c #AC0000", "6 c #D00000", "7 c #E40000", "8 c #F70000", "9 c #F80000", "0 c #F50000", "a c #ED0000", "b c #DE0000", "c c #960000", "d c #000098", "e c #4F0027", "f c #BA0000", "g c #D80000", "h c #EA0000", "i c #F40000", "j c #FA0000", "k c #FC0000", "l c #C80000", "m c #A50000", "n c #000084", "o c #580022", "p c #D70000", "q c #F90000", "r c #FB0000", "s c #F10000", "t c #CA0000", "u c #A70000", "v c #00006E", "w c #500024", "x c #B40000", "y c #D20000", "z c #E60000", "A c #F60000", "B c #F30000", "C c #EB0000", "D c #C10000", "E c #9E0000", "F c #0000F5", "G c #000060", "H c #28003E", "I c #A40000", "J c #C60000", "K c #DB0000", "L c #EE0000", "M c #D10000", "N c #840000", "O c #0000E4", "P c #04005A", "Q c #79000A", "R c #B30000", "S c #BC0000", "T c #920000", "U c #0000CE", "V c #1A009B", "W c #880008", "X c #AE0000", "Y c #C70000", "Z c #970000", "` c #0000BA", " . c #0000EC", ".. c #1600C3", "+. c #680028", "@. c #940000", "#. c #A10000", "$. c #A20000", "%. c #6C0030", "&. c #38006D", "*. c #0000A4", "=. c #000057", "-. c #000051", ";. c #00004C", ">. c #000096", ",. c #0000B7", "'. c #0000D4", "). c #1600BA", "!. c #2A009C", "~. c #1600C5", "{. c #0000F1", "]. c #0000D2", "^. c #0000B1", "/. c #00008E", "(. c #000039", "_. c #00003C", ":. c #000054", "<. c #000075", "[. c #000097", "}. c #0000B4", "|. c #0000E9", "1. c #0000C9", "2. c #0000A8", "3. c #000086", "4. c #000064", "5. c #00004D", " . ", " + @ # $ % & * = ", " - @ @ ; > , ' ) ! ~ { ] ", " . ^ @ / ( _ : < [ } | 1 2 ] ", " . 3 @ 4 5 6 7 } 8 9 0 a b & c ", " . d @ e f g h i j k 9 } 1 l m ", " . n @ o f p < i q r 9 s 1 t u ", " . v @ w x y z [ 0 A B C ~ D E ", " F G @ H I J K z a L C ! M ] N ", " O @ @ P Q R t g b ) ~ 6 S T ", " U @ @ @ V W X % Y l , * Z ", ". ` @ @ @ ...+.@.#.$.Z %.&. ", ". *.=.-.;.>.,.'.).!.!.~.. ", ". {.].^./.v ;.(._.:.<.[.}. ", " . . . . . |.1.2.3.4.5. ", " . . . . "}; mm3d-1.3.7/desktop/Makefile.am0000644000175000017500000000067410744511356013025 00000000000000EXTRA_DIST = \ mm3d.desktop \ x-mm3d.desktop \ mm3d.xpm \ mm3d-16.xpm all: install: $(INSTALL) -d $(DESTDIR)$(datadir)/applications/ $(INSTALL) -d $(DESTDIR)$(datadir)/mimelnk/application/ $(INSTALL) -d $(DESTDIR)$(datadir)/pixmaps/ ${INSTALL} -m 0644 mm3d.desktop $(DESTDIR)$(datadir)/applications/ ${INSTALL} -m 0644 x-mm3d.desktop $(DESTDIR)$(datadir)/mimelnk/application/ ${INSTALL} -m 0644 *.xpm $(DESTDIR)$(datadir)/pixmaps/ mm3d-1.3.7/desktop/x-mm3d.desktop0000644000175000017500000000017510744511356013465 00000000000000[Desktop Entry] Encoding=UTF-8 Comment=mm3d model Type=MimeType MimeType=application/x-mm3d Icon=mm3d Patterns=*.mm3d;*.MM3D mm3d-1.3.7/AUTHORS0000644000175000017500000000056610744511356010370 00000000000000Primary development: Kevin Worcester http://www.misfitcode.com/misfitmodel3d/contact.html Texture reload and Snap Together command: Johannes Kroll Various bug fixes and feature enhancements: Ainsley Pereira Initial Win32 Port Patch: Georg Hennig http://www.hennigbuam.de/georg/ Initial MD3 Filter: Russell Valentine http://coldstonelabs.org/ mm3d-1.3.7/COPYING0000644000175000017500000004361510744511356010355 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. mm3d-1.3.7/INSTALL.WIN320000644000175000017500000000415610744511356011151 00000000000000Misfit Model 3D Installation For Win32 ====================================== Misfit Model 3D is known to run on Windows 2000 and Windows XP. Windows 95, 98, and ME are untested and may or may not work. Misfit Model 3D for Win32 requires the mingw environment and the Open Source version of Qt 4 for Win32. To run binaries of mm3d you only need the qt and mingw DLLs, which are provided with the binary distribution. To build from source you must have a development environment set up with mingw and qt4. Note that plugins are not currently available on Windows. Binary Installation =================== Get the latest installer from the web site. It should have a filename like 'mm3d-X_X_X-win32-installer.exe'. Run the installer and select an install location. Optionally you may choose to enable file assciations with Misfit Model 3D. By default only .mm3d is associated. Prerequisites ============= You can get Qt 4 here: http://trolltech.com/developer/downloads/qt/windows You can get mingw using Qt 4's binary installer, or download and install mingw yourself from the official website: http://www.mingw.org/ You must have your QTDIR environment variable set to the root Qt directory (for example, c:\Qt\4.0.1). The Mingw and Qt bin directories must be in your path. Build Instructions ================== Once you have installed mingw and Qt, do the following steps: 1. Make sure QTDIR is set and mingw's bin directory and Qt's bin directory is in your PATH 2. Open a cmd prompt and go to the mm3d-X.X.X directory 3. Run 'mingw32-make -f Makefile.mingw' Install Instructions ==================== 1. Run 'install.bat' from the mm3d-X.X.X directory. The install.bat file does not create any program menu or desktop shortcuts. If you want shortcuts you must create them manually, or use the binary installer. Optionally, you can install NSIS and put the qt and mingw dlls in your mm3d-X.X.X/dll directory and then build the installer. This will create shortcuts and some registry keys. You can get NSIS here: http://nsis.sourceforge.net/ mm3d-1.3.7/depcomp0000755000175000017500000003710010744511356010667 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2005-07-09.11 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mecanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: mm3d-1.3.7/Makefile.am0000644000175000017500000000173510744511356011353 00000000000000EXTRA_DIST = Makefile.mingw \ config.h.mingw \ cleanup.sh \ mm3d-win32-installer.nsi \ TRANSLATORS \ INSTALL.WIN32 \ install.bat \ mm3d.reg SUBDIRS = src plugins i18n doc desktop man DESTDIR = src MAC_APP = $(PACKAGE).app $(MAC_APP): $(MAC_APP)/Contents/PkgInfo $(MAC_APP)/Contents/Info.plist @cp $(DESTDIR)/$(PACKAGE) $(MAC_APP)/Contents/MacOS/$(PACKAGE) $(MAC_APP)/Contents/PkgInfo: @test -d $(MAC_APP)/Contents/MacOS/ || mkdir -p $(MAC_APP)/Contents/MacOS/ @rm -f $(MAC_APP)/Contents/PkgInfo @echo "APPL????" > $(MAC_APP)/Contents/PkgInfo $(MAC_APP)/Contents/Info.plist: @test -d $(MAC_APP)/Contents/MacOS/ || mkdir -p $(MAC_APP)/Contents/MacOS/ @rm -f $(MAC_APP)/Contents/Info.plist @echo "" > $(MAC_APP)/Contents/Info.plist @defaults write $(PWD)/$(MAC_APP)/Contents/Info '{"CFBundlePackageType"=APPL;}'; @defaults write $(PWD)/$(MAC_APP)/Contents/Info "CFBundleSignature" "????" @defaults write $(PWD)/$(MAC_APP)/Contents/Info "CFBundleExecutable" $(PACKAGE) mm3d-1.3.7/install.bat0000755000175000017500000000031110744511356011445 00000000000000@echo off set MM3DDIR="c:\Program Files\Misfit Model 3D" regedit /i /s mm3d.reg mkdir %MM3DDIR% mkdir %MM3DDIR%\doc xcopy /q /y /r mm3d.exe %MM3DDIR% xcopy /q /y /r /e doc %MM3DDIR%\doc mm3d-1.3.7/cleanup.sh0000755000175000017500000000010510744511356011273 00000000000000#!/bin/sh rm `find . -iname "*.base.*"` rm `find . -iname "*.moc.*"` mm3d-1.3.7/plugins/0000777000175000017500000000000011031450304011037 500000000000000mm3d-1.3.7/plugins/Makefile.in0000644000175000017500000002056711025503556013045 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = plugins DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BYTEORDER = @BYTEORDER@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_PROFILE = @CORE_PROFILE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLOPEN_LIBS = @DLOPEN_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ HAVE_QT4 = @HAVE_QT4@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ LUALIB_CCFLAGS = @LUALIB_CCFLAGS@ LUALIB_DIR = @LUALIB_DIR@ LUALIB_LIBS = @LUALIB_LIBS@ LUA_CCFLAGS = @LUA_CCFLAGS@ LUA_DIR = @LUA_DIR@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PROFILE = @PROFILE@ QGL_LIBS = @QGL_LIBS@ QT_CXXFLAGS = @QT_CXXFLAGS@ QT_DIR = @QT_DIR@ QT_LIBS = @QT_LIBS@ QT_LRELEASE = @QT_LRELEASE@ QT_MOC = @QT_MOC@ QT_UIC = @QT_UIC@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plugins/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu plugins/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh uninstall-info-am: tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-exec \ install-exec-am install-info install-info-am install-man \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ uninstall-info-am all: install: $(INSTALL) -d $(DESTDIR)$(datadir)/mm3d/plugins/1.3 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mm3d-1.3.7/plugins/Makefile.am0000644000175000017500000000010510744511356013022 00000000000000 all: install: $(INSTALL) -d $(DESTDIR)$(datadir)/mm3d/plugins/1.3 mm3d-1.3.7/mkinstalldirs0000755000175000017500000000662210744511356012125 00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy scriptversion=2005-06-29.22 # Original author: Noah Friedman # Created: 1993-05-16 # Public domain. # # This file is maintained in Automake, please report # bugs to or send patches to # . errstatus=0 dirmode= usage="\ Usage: mkinstalldirs [-h] [--help] [--version] [-m MODE] DIR ... Create each directory DIR (with mode MODE, if specified), including all leading file name components. Report bugs to ." # process command line arguments while test $# -gt 0 ; do case $1 in -h | --help | --h*) # -h for help echo "$usage" exit $? ;; -m) # -m PERM arg shift test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } dirmode=$1 shift ;; --version) echo "$0 $scriptversion" exit $? ;; --) # stop option processing shift break ;; -*) # unknown option echo "$usage" 1>&2 exit 1 ;; *) # first non-opt arg break ;; esac done for file do if test -d "$file"; then shift else break fi done case $# in 0) exit 0 ;; esac # Solaris 8's mkdir -p isn't thread-safe. If you mkdir -p a/b and # mkdir -p a/c at the same time, both will detect that a is missing, # one will create a, then the other will try to create a and die with # a "File exists" error. This is a problem when calling mkinstalldirs # from a parallel make. We use --version in the probe to restrict # ourselves to GNU mkdir, which is thread-safe. case $dirmode in '') if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" else # On NextStep and OpenStep, the `mkdir' command does not # recognize any option. It will interpret all options as # directories to create, and then abort because `.' already # exists. test -d ./-p && rmdir ./-p test -d ./--version && rmdir ./--version fi ;; *) if mkdir -m "$dirmode" -p --version . >/dev/null 2>&1 && test ! -d ./--version; then echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" else # Clean up after NextStep and OpenStep mkdir. for d in ./-m ./-p ./--version "./$dirmode"; do test -d $d && rmdir $d done fi ;; esac for file do case $file in /*) pathcomp=/ ;; *) pathcomp= ;; esac oIFS=$IFS IFS=/ set fnord $file shift IFS=$oIFS for d do test "x$d" = x && continue pathcomp=$pathcomp$d case $pathcomp in -*) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr else if test ! -z "$dirmode"; then echo "chmod $dirmode $pathcomp" lasterr= chmod "$dirmode" "$pathcomp" || lasterr=$? if test ! -z "$lasterr"; then errstatus=$lasterr fi fi fi fi pathcomp=$pathcomp/ done done exit $errstatus # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: mm3d-1.3.7/src/0000777000175000017500000000000011031450304010145 500000000000000mm3d-1.3.7/src/stdtools.cc0000644000175000017500000000743610751252501012264 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "stdtools.h" #include "config.h" // Tools to include in build #include "scaletool.h" #include "sheartool.h" #include "selectvertextool.h" #include "selectfacetool.h" #include "selectconnectedtool.h" #include "selectgrouptool.h" #include "selectbonetool.h" #include "selectpointtool.h" #include "selectprojtool.h" #include "movetool.h" #include "dragvertextool.h" #include "rotatetool.h" #include "atrneartool.h" #include "atrfartool.h" #include "vertextool.h" #include "rectangletool.h" #include "jointtool.h" #include "pointtool.h" #include "projtool.h" #include "cubetool.h" #include "ellipsetool.h" #include "extrudetool.h" #include "cylindertool.h" #include "torustool.h" #include "polytool.h" #include "bgscaletool.h" #include "bgmovetool.h" #include "toolbox.h" #include "log.h" static void _new_std_tools( Toolbox * toolbox ) { log_debug( "initializing standard tools\n" ); ::Tool * tool; // These are cleaned up by the toolbox tool = new SelectVertexTool(); toolbox->registerTool( tool ); tool = new SelectFaceTool(); toolbox->registerTool( tool ); tool = new SelectConnectedTool(); toolbox->registerTool( tool ); tool = new SelectGroupTool(); toolbox->registerTool( tool ); tool = new SelectBoneTool(); toolbox->registerTool( tool ); tool = new SelectPointTool(); toolbox->registerTool( tool ); tool = new SelectProjectionTool(); toolbox->registerTool( tool ); tool = new ToolSeparator(); toolbox->registerTool( tool ); tool = new MoveTool(); toolbox->registerTool( tool ); tool = new RotateTool(); toolbox->registerTool( tool ); tool = new ScaleTool(); toolbox->registerTool( tool ); tool = new ShearTool(); toolbox->registerTool( tool ); tool = new ExtrudeTool(); toolbox->registerTool( tool ); tool = new DragVertexTool(); toolbox->registerTool( tool ); tool = new ToolSeparator(); toolbox->registerTool( tool ); tool = new AttractNearTool(); toolbox->registerTool( tool ); tool = new AttractFarTool(); toolbox->registerTool( tool ); tool = new BgMoveTool(); toolbox->registerTool( tool ); tool = new BgScaleTool(); toolbox->registerTool( tool ); tool = new ToolSeparator(); toolbox->registerTool( tool ); tool = new VertexTool(); toolbox->registerTool( tool ); tool = new CubeTool(); toolbox->registerTool( tool ); tool = new EllipsoidTool(); toolbox->registerTool( tool ); tool = new CylinderTool(); toolbox->registerTool( tool ); tool = new TorusTool(); toolbox->registerTool( tool ); tool = new PolyTool(); toolbox->registerTool( tool ); tool = new RectangleTool(); toolbox->registerTool( tool ); tool = new JointTool(); toolbox->registerTool( tool ); tool = new PointTool(); toolbox->registerTool( tool ); tool = new ProjectionTool(); toolbox->registerTool( tool ); } int init_std_tools() { Toolbox::registerToolFunction( _new_std_tools ); return 0; } mm3d-1.3.7/src/depui/0000777000175000017500000000000011031450274011261 500000000000000mm3d-1.3.7/src/depui/errorobj.h0000644000175000017500000000271210746740321013203 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __ERROROBJ_H #define __ERROROBJ_H #include #include #include "model.h" #include "texture.h" class ErrorObject : public QObject { Q_OBJECT public: ErrorObject( QObject * parent = NULL ); virtual ~ErrorObject( ); QString getModelErrorString( Model::ModelErrorE err, Model * model = NULL ); QString getTextureErrorString( Texture::ErrorE err ); }; extern ErrorObject g_errorObject; // Convenience functions QString modelErrStr( Model::ModelErrorE err, Model * model = NULL ); QString textureErrStr( Texture::ErrorE err ); #endif // __ERROROBJ_H mm3d-1.3.7/src/depui/textureframe.moc.cc0000644000175000017500000000423511025504141014774 00000000000000/**************************************************************************** ** Meta object code from reading C++ file 'textureframe.h' ** ** Created: Mon Jun 16 08:36:01 2008 ** by: The Qt Meta Object Compiler version 59 (Qt 4.2.3) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ #include "textureframe.h" #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'textureframe.h' doesn't include ." #elif Q_MOC_OUTPUT_REVISION != 59 #error "This file was generated using the moc from 4.2.3. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif static const uint qt_meta_data_TextureFrame[] = { // content: 1, // revision 0, // classname 0, 0, // classinfo 2, 10, // methods 0, 0, // properties 0, 0, // enums/sets // slots: signature, parameters, type, tag, flags 16, 14, 13, 13, 0x0a, 53, 43, 13, 13, 0x0a, 0 // eod }; static const char qt_meta_stringdata_TextureFrame[] = { "TextureFrame\0\0e\0resizeEvent(QResizeEvent*)\0" "textureId\0textureChangedEvent(int)\0" }; const QMetaObject TextureFrame::staticMetaObject = { { &QFrame::staticMetaObject, qt_meta_stringdata_TextureFrame, qt_meta_data_TextureFrame, 0 } }; const QMetaObject *TextureFrame::metaObject() const { return &staticMetaObject; } void *TextureFrame::qt_metacast(const char *_clname) { if (!_clname) return 0; if (!strcmp(_clname, qt_meta_stringdata_TextureFrame)) return static_cast(const_cast< TextureFrame*>(this)); return QFrame::qt_metacast(_clname); } int TextureFrame::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QFrame::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: resizeEvent((*reinterpret_cast< QResizeEvent*(*)>(_a[1]))); break; case 1: textureChangedEvent((*reinterpret_cast< int(*)>(_a[1]))); break; } _id -= 2; } return _id; } mm3d-1.3.7/src/depui/modelviewport.h0000644000175000017500000001462110746740356014271 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __MVIEWPORT_H #define __MVIEWPORT_H #include #include #include #include #include #include #include "tool.h" #include "decal.h" #include "texture.h" #include #include using std::list; class Model; class Decal; class Toolbox; class QTimer; typedef list DecalList; class ModelViewport : public QGLWidget, public Tool::Parent { Q_OBJECT public: enum { MAX_VERTICAL_UNITS = 32767, MAX_HORIZONTAL_UNITS = 32767 }; enum _ViewOptions_e { ViewWireframe, ViewFlat, ViewSmooth, ViewTexture, ViewAlpha }; typedef enum _ViewOptions_e ViewOptionsE; enum _MouseOperation_e { MO_None, MO_Tool, MO_Pan, MO_PanButton, MO_Rotate, MO_RotateButton, }; typedef enum _MouseOperation_e MouseOperationE; enum _ScrollButton_e { ScrollButtonPan, ScrollButtonLeft, ScrollButtonRight, ScrollButtonUp, ScrollButtonDown, ScrollButtonMAX }; typedef enum _ScrollButton_e ScrollButtonE; struct _ViewState_t { ViewDirectionE direction; double rotation[3]; double translation[3]; double zoom; }; typedef struct _ViewState_t ViewStateT; ModelViewport( QWidget * parent = NULL ); virtual ~ModelViewport(); void freeTextures(); double getZoomLevel() { return m_zoomLevel; }; void frameArea( double x1, double y1, double z1, double x2, double y2, double z2 ); void zoomIn(); void zoomOut(); void scrollUp(); void scrollDown(); void scrollLeft(); void scrollRight(); void rotateUp(); void rotateDown(); void rotateLeft(); void rotateRight(); void rotateClockwise(); void rotateCounterClockwise(); void rotateViewport( double x, double y, double z = 0.0 ); void setModel( Model * model ) { m_model = model; }; void setToolbox( Toolbox * toolbox ) { m_toolbox = toolbox; }; int constructButtonState( QMouseEvent * e ); // Tool::Parent methods Model * getModel() { return m_model; }; ViewDirectionE getViewDirection() { return m_viewDirection; }; void updateView(); void update3dView(); void updateAllViews() { emit modelUpdated(); }; void getParentXYValue( int x, int y, double & xval, double & yval, bool selected ); void getRawParentXYValue( int x, int y, double & xval, double & yval ); const Matrix & getParentViewMatrix() const { return m_viewMatrix; }; const Matrix & getParentViewInverseMatrix() const { return m_invMatrix; }; bool getXValue( int x, int y, double * val ); bool getYValue( int x, int y, double * val ); bool getZValue( int x, int y, double * val ); void addDecal( Decal * decal ); void removeDecal( Decal * decal ); void copyContentsToTexture( Texture * tex ); void updateCaptureGL(); signals: void zoomLevelChanged( const QString & zoomStr ); void viewDirectionChanged( int dir ); void modelUpdated(); void viewportSaveState( int slotNumber, const ModelViewport::ViewStateT & viewState ); void viewportRecallState( int slotNumber ); public slots: void viewChangeEvent( int dir ); void setZoomLevel( double zoomLevel ); void setViewState( const ModelViewport::ViewStateT & viewState ); void wireframeEvent(); void flatEvent(); void smoothEvent(); void textureEvent(); void alphaEvent(); void scrollTimeout(); protected slots: void wheelEvent( QWheelEvent * e ); void mouseMoveEvent( QMouseEvent * e ); void mousePressEvent( QMouseEvent * e ); void mouseReleaseEvent( QMouseEvent * e ); void keyPressEvent( QKeyEvent * e ); void focusInEvent( QFocusEvent * e ); void focusOutEvent( QFocusEvent * e ); //void dragEnterEvent( QDragMoveEvent * e ); protected: void initializeGL(); void paintGL(); void resizeGL( int w, int h ); void checkGlErrors(); void updateBackground(); void adjustViewport(); void setViewportDraw(); void setViewportOverlay(); void drawGridLines(); void drawOrigin(); void drawBackground(); void drawOverlay(); void makeTextureFromImage( const QImage & i, GLuint & t ); Model * m_model; MouseOperationE m_operation; int m_activeButton; ViewDirectionE m_viewDirection; Matrix m_viewMatrix; Matrix m_invMatrix; double m_centerX; double m_centerY; double m_centerZ; double m_arcballPoint[3]; double m_rotX; double m_rotY; double m_rotZ; double m_width; double m_height; double m_zoomLevel; double m_far; double m_near; double m_farOrtho; double m_nearOrtho; int m_viewportWidth; int m_viewportHeight; GLuint m_backgroundTexture; Texture * m_texture; std::string m_backgroundFile; QTimer * m_scrollTimer; bool m_inOverlay; ScrollButtonE m_overlayButton; GLuint m_scrollTextures[2]; bool m_capture; bool m_texturesLoaded; ViewOptionsE m_viewOptions; QPoint m_scrollStartPosition; QColor m_backColor; DecalList m_decals; Toolbox * m_toolbox; }; #endif // __MVIEWPORT_H mm3d-1.3.7/src/depui/errorobj.moc.cc0000644000175000017500000000327011025504136014107 00000000000000/**************************************************************************** ** Meta object code from reading C++ file 'errorobj.h' ** ** Created: Mon Jun 16 08:35:58 2008 ** by: The Qt Meta Object Compiler version 59 (Qt 4.2.3) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ #include "errorobj.h" #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'errorobj.h' doesn't include ." #elif Q_MOC_OUTPUT_REVISION != 59 #error "This file was generated using the moc from 4.2.3. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif static const uint qt_meta_data_ErrorObject[] = { // content: 1, // revision 0, // classname 0, 0, // classinfo 0, 0, // methods 0, 0, // properties 0, 0, // enums/sets 0 // eod }; static const char qt_meta_stringdata_ErrorObject[] = { "ErrorObject\0" }; const QMetaObject ErrorObject::staticMetaObject = { { &QObject::staticMetaObject, qt_meta_stringdata_ErrorObject, qt_meta_data_ErrorObject, 0 } }; const QMetaObject *ErrorObject::metaObject() const { return &staticMetaObject; } void *ErrorObject::qt_metacast(const char *_clname) { if (!_clname) return 0; if (!strcmp(_clname, qt_meta_stringdata_ErrorObject)) return static_cast(const_cast< ErrorObject*>(this)); return QObject::qt_metacast(_clname); } int ErrorObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QObject::qt_metacall(_c, _id, _a); if (_id < 0) return _id; return _id; } mm3d-1.3.7/src/depui/textureframe.h0000644000175000017500000000361610746740370014102 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __TEXFRAME_H #define __TEXFRAME_H #include #include class Model; class TextureWidget; class Texture; class TextureFrame : public QFrame { Q_OBJECT public: TextureFrame( QWidget * parent = NULL ); virtual ~TextureFrame(); void setModel( Model * model ); void set3d( bool o ); void resizeTexture( int width, int height ); void updateSize(); void sizeOverride( int width, int height ); TextureWidget * getTextureWidget() { return m_textureWidget; }; void setTexture( int materialId, Texture * tex ); enum { PAD_SIZE = 6 }; public slots: void resizeEvent( QResizeEvent * e ); void textureChangedEvent( int textureId ); protected: TextureWidget * m_textureWidget; int m_materialId; Texture * m_texture; bool m_3d; bool m_overrideSize; int m_overWidth; int m_overHeight; Model * m_model; }; #endif // __TEXFRAME_H mm3d-1.3.7/src/depui/texwidget.moc.cc0000644000175000017500000001132111025504142014260 00000000000000/**************************************************************************** ** Meta object code from reading C++ file 'texwidget.h' ** ** Created: Mon Jun 16 08:36:02 2008 ** by: The Qt Meta Object Compiler version 59 (Qt 4.2.3) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ #include "texwidget.h" #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'texwidget.h' doesn't include ." #elif Q_MOC_OUTPUT_REVISION != 59 #error "This file was generated using the moc from 4.2.3. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif static const uint qt_meta_data_TextureWidget[] = { // content: 1, // revision 0, // classname 0, 0, // classinfo 16, 10, // methods 0, 0, // properties 0, 0, // enums/sets // signals: signature, parameters, type, tag, flags 15, 14, 14, 14, 0x05, 41, 14, 14, 14, 0x05, 71, 14, 14, 14, 0x05, 91, 14, 14, 14, 0x05, 127, 115, 14, 14, 0x05, 159, 14, 14, 14, 0x05, 190, 182, 14, 14, 0x05, // slots: signature, parameters, type, tag, flags 216, 14, 14, 14, 0x0a, 235, 14, 14, 14, 0x0a, 246, 14, 14, 14, 0x0a, 259, 14, 14, 14, 0x0a, 272, 14, 14, 14, 0x0a, 286, 14, 14, 14, 0x0a, 295, 14, 14, 14, 0x0a, 305, 14, 14, 14, 0x0a, 326, 321, 14, 14, 0x0a, 0 // eod }; static const char qt_meta_stringdata_TextureWidget[] = { "TextureWidget\0\0updateCoordinatesSignal()\0" "updateCoordinatesDoneSignal()\0" "updateRangeSignal()\0updateRangeDoneSignal()\0" "xDiff,yDiff\0updateSeamSignal(double,double)\0" "updateSeamDoneSignal()\0zoomStr\0" "zoomLevelChanged(QString)\0animationTimeout()\0" "scrollUp()\0scrollDown()\0scrollLeft()\0" "scrollRight()\0zoomIn()\0zoomOut()\0" "scrollTimeout()\0zoom\0setZoomLevel(double)\0" }; const QMetaObject TextureWidget::staticMetaObject = { { &QGLWidget::staticMetaObject, qt_meta_stringdata_TextureWidget, qt_meta_data_TextureWidget, 0 } }; const QMetaObject *TextureWidget::metaObject() const { return &staticMetaObject; } void *TextureWidget::qt_metacast(const char *_clname) { if (!_clname) return 0; if (!strcmp(_clname, qt_meta_stringdata_TextureWidget)) return static_cast(const_cast< TextureWidget*>(this)); return QGLWidget::qt_metacast(_clname); } int TextureWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QGLWidget::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: updateCoordinatesSignal(); break; case 1: updateCoordinatesDoneSignal(); break; case 2: updateRangeSignal(); break; case 3: updateRangeDoneSignal(); break; case 4: updateSeamSignal((*reinterpret_cast< double(*)>(_a[1])),(*reinterpret_cast< double(*)>(_a[2]))); break; case 5: updateSeamDoneSignal(); break; case 6: zoomLevelChanged((*reinterpret_cast< QString(*)>(_a[1]))); break; case 7: animationTimeout(); break; case 8: scrollUp(); break; case 9: scrollDown(); break; case 10: scrollLeft(); break; case 11: scrollRight(); break; case 12: zoomIn(); break; case 13: zoomOut(); break; case 14: scrollTimeout(); break; case 15: setZoomLevel((*reinterpret_cast< double(*)>(_a[1]))); break; } _id -= 16; } return _id; } // SIGNAL 0 void TextureWidget::updateCoordinatesSignal() { QMetaObject::activate(this, &staticMetaObject, 0, 0); } // SIGNAL 1 void TextureWidget::updateCoordinatesDoneSignal() { QMetaObject::activate(this, &staticMetaObject, 1, 0); } // SIGNAL 2 void TextureWidget::updateRangeSignal() { QMetaObject::activate(this, &staticMetaObject, 2, 0); } // SIGNAL 3 void TextureWidget::updateRangeDoneSignal() { QMetaObject::activate(this, &staticMetaObject, 3, 0); } // SIGNAL 4 void TextureWidget::updateSeamSignal(double _t1, double _t2) { void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)), const_cast(reinterpret_cast(&_t2)) }; QMetaObject::activate(this, &staticMetaObject, 4, _a); } // SIGNAL 5 void TextureWidget::updateSeamDoneSignal() { QMetaObject::activate(this, &staticMetaObject, 5, 0); } // SIGNAL 6 void TextureWidget::zoomLevelChanged(QString _t1) { void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 6, _a); } mm3d-1.3.7/src/depui/Makefile.in0000644000175000017500000003303411025503557013253 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = src/depui DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libdepui_a_AR = $(AR) $(ARFLAGS) libdepui_a_LIBADD = am__objects_1 = errorobj.moc.$(OBJEXT) modelviewport.moc.$(OBJEXT) \ textureframe.moc.$(OBJEXT) texwidget.moc.$(OBJEXT) am__objects_2 = am_libdepui_a_OBJECTS = errorobj.$(OBJEXT) modelviewport.$(OBJEXT) \ textureframe.$(OBJEXT) texwidget.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) libdepui_a_OBJECTS = $(am_libdepui_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libdepui_a_SOURCES) DIST_SOURCES = $(libdepui_a_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BYTEORDER = @BYTEORDER@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_PROFILE = @CORE_PROFILE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLOPEN_LIBS = @DLOPEN_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ HAVE_QT4 = @HAVE_QT4@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ LUALIB_CCFLAGS = @LUALIB_CCFLAGS@ LUALIB_DIR = @LUALIB_DIR@ LUALIB_LIBS = @LUALIB_LIBS@ LUA_CCFLAGS = @LUA_CCFLAGS@ LUA_DIR = @LUA_DIR@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PROFILE = @PROFILE@ QGL_LIBS = @QGL_LIBS@ QT_CXXFLAGS = @QT_CXXFLAGS@ QT_DIR = @QT_DIR@ QT_LIBS = @QT_LIBS@ QT_LRELEASE = @QT_LRELEASE@ QT_MOC = @QT_MOC@ QT_UIC = @QT_UIC@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ noinst_LIBRARIES = libdepui.a libdepui_HFILES = \ errorobj.h \ modelviewport.h \ textureframe.h \ texwidget.h libdepui_MOC = \ errorobj.moc.cc \ modelviewport.moc.cc \ textureframe.moc.cc \ texwidget.moc.cc libdepui_a_SOURCES = \ errorobj.cc \ modelviewport.cc \ textureframe.cc \ texwidget.cc \ $(libdepui_MOC) \ $(libdepui_HFILES) AM_CPPFLAGS = $(CORE_PROFILE) -coverage -Wall -I../libmm3d -I../mm3dcore -I../ -DMM3D_EDIT $(all_includes) $(QT_CXXFLAGS) $(LUALIB_CCFLAGS) $(GL_CFLAGS) CLEANFILES = $(libdepui_MOC) *.gcno *.gcda all: all-am .SUFFIXES: .SUFFIXES: .cc .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/depui/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu src/depui/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libdepui.a: $(libdepui_a_OBJECTS) $(libdepui_a_DEPENDENCIES) -rm -f libdepui.a $(libdepui_a_AR) libdepui.a $(libdepui_a_OBJECTS) $(libdepui_a_LIBADD) $(RANLIB) libdepui.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errorobj.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errorobj.moc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modelviewport.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modelviewport.moc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textureframe.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textureframe.moc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texwidget.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texwidget.moc.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am %.moc.cc: %.h $(QT_MOC) -o $@ $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mm3d-1.3.7/src/depui/texwidget.h0000644000175000017500000001764010746740404013373 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __TEXWIDGET_H #define __TEXWIDGET_H #include #include #include #include #include #include class Texture; class Model; class QTimer; class TextureWidget : public QGLWidget { Q_OBJECT public: enum _DrawMode_e { DM_Edit, DM_Edges, DM_Filled, DM_FilledEdges, DM_MAX }; typedef enum _DrawMode_e DrawModeE; enum _MouseOperation_e { MouseMove, MouseSelect, MouseScale, MouseRotate, MouseRange }; typedef enum _MouseOperation_e MouseOperationE; enum _ScrollButton_e { ScrollButtonPan, ScrollButtonLeft, ScrollButtonRight, ScrollButtonUp, ScrollButtonDown, ScrollButtonMAX }; typedef enum _ScrollButton_e ScrollButtonE; struct _TextureVertex_t { double s; double t; bool selected; }; struct _RotateVertex_t { unsigned v; double x; double y; }; typedef struct _TextureVertex_t TextureVertexT; typedef std::vector< TextureVertexT * > TextureVertexVector; typedef struct _RotateVertex_t RotateVertexT; typedef std::vector< RotateVertexT * > RotateVertexVector; struct _TextureTriangle_t { int vertex[3]; }; typedef struct _TextureTriangle_t TextureTriangleT; typedef std::vector< TextureTriangleT * > TextureTriangleVector; TextureWidget( QWidget * parent = NULL ); virtual ~TextureWidget(); void setModel( Model * model ); void setTexture( int materialId, Texture * texture ); void setInteractive( bool o ); void set3d( bool o ); void setTextureCount( unsigned c ); void setSClamp( bool o ) { m_sClamp = o; setTexture( m_materialId, m_texture ); }; void setTClamp( bool o ) { m_tClamp = o; setTexture( m_materialId, m_texture ); }; void setDrawMode( DrawModeE dm ); void setDrawVertices( bool dv ) { m_drawVertices = dv; }; void setMouseOperation( MouseOperationE op ); void setScaleKeepAspect( bool o ) { m_scaleKeepAspect = o; }; void setScaleFromCenter( bool o ) { m_scaleFromCenter = o; }; void setSolidBackground( bool o ) { m_solidBackground = o; }; int addVertex( double t, double s ); int addTriangle( int v1, int v2, int v3 ); void clearCoordinates(); void getCoordinates( int tri, float * s, float * t ); // This is min/max of the current viewport, not of the // vertices in the viewport double getMinViewCoord() { return m_xMin; }; double getMaxViewCoord() { return m_xMax; }; void setRange( double xMin, double yMin, double xMax, double yMax ); void getRange( double & xMin, double & yMin, double & xMax, double & yMax ); // paint my scene on another OpenGL widget void paintOnGlWidget( QGLWidget * w ); public slots: void animationTimeout(); void scrollUp(); void scrollDown(); void scrollLeft(); void scrollRight(); void zoomIn(); void zoomOut(); void scrollTimeout(); void setZoomLevel( double zoom ); signals: void updateCoordinatesSignal(); void updateCoordinatesDoneSignal(); void updateRangeSignal(); void updateRangeDoneSignal(); void updateSeamSignal( double xDiff, double yDiff ); void updateSeamDoneSignal(); void zoomLevelChanged( QString zoomStr ); protected: virtual void mousePressEvent( QMouseEvent * e ); virtual void mouseReleaseEvent( QMouseEvent * e ); virtual void mouseMoveEvent( QMouseEvent * e ); virtual void wheelEvent( QWheelEvent * e ); virtual void keyPressEvent( QKeyEvent * e ); void moveSelectedVertices( double x, double y ); void updateSelectRegion( double x, double y ); void startScale( double x, double y ); void rotateSelectedVertices( double angle ); void scaleSelectedVertices( double x, double y ); void setViewportDraw(); void setViewportOverlay(); void drawTriangles(); void drawOverlay(); void makeTextureFromImage( const QImage & i, GLuint & t ); void selectDone(); void drawSelectBox(); void drawRangeBox(); void drawRotationPoint(); void clearSelected(); double getWindowXCoord( int x ); double getWindowYCoord( int y ); void updateCursorShape( int x, int y ); void getDragDirections( double x, double y, bool & all, bool & top, bool & bottom, bool & left, bool & right ); void setDragCursor( bool all, bool top, bool bottom, bool left, bool right ); void initializeGL(); void paintGL(); void resizeGL( int w, int h ); void paintInternal(); void updateViewport(); void freeRotateVertices(); double distance( const double &, const double &, const double &, const double & ); double max( const double &, const double & ); int m_viewportWidth; int m_viewportHeight; bool m_sClamp; bool m_tClamp; double m_zoom; double m_xCenter; double m_yCenter; int m_lastXPos; int m_lastYPos; Model * m_model; int m_materialId; Texture * m_texture; GLuint m_glTexture; QTimer * m_scrollTimer; ScrollButtonE m_overlayButton; GLuint m_scrollTextures[2]; TextureVertexVector m_vertices; TextureTriangleVector m_triangles; RotateVertexVector m_rotateVertices; DrawModeE m_drawMode; bool m_drawVertices; bool m_solidBackground; MouseOperationE m_operation; bool m_scaleKeepAspect; bool m_scaleFromCenter; bool m_selecting; bool m_drawBounding; bool m_drawRange; bool m_interactive; bool m_3d; int m_button; // For 3d view QTimer * m_animTimer; double m_xMin; double m_xMax; double m_yMin; double m_yMax; // For select double m_xSel1; double m_ySel1; double m_xSel2; double m_ySel2; // For rotation double m_xRotPoint; double m_yRotPoint; double m_xRotStart; double m_yRotStart; double m_startAngle; // For projection range double m_xRangeMin; double m_yRangeMin; double m_xRangeMax; double m_yRangeMax; // For projection move/resize bool m_dragAll; bool m_dragTop; bool m_dragBottom; bool m_dragLeft; bool m_dragRight; // For scale typedef struct _ScaleVertices_t { unsigned index; double x; double y; } ScaleVerticesT; typedef std::list ScaleVerticesList; double m_farX; double m_farY; double m_centerX; double m_centerY; double m_startLengthX; double m_startLengthY; ScaleVerticesList m_scaleList; }; #endif // __TEXWIDGET_H mm3d-1.3.7/src/depui/texwidget.cc0000644000175000017500000016051211000471710013507 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "texwidget.h" #include "texture.h" #include "model.h" #include "log.h" #include "mm3dport.h" #include #include #include #include #include #include #include #include "pixmap/arrow.xpm" #include "pixmap/crosshairrow.xpm" #define VP_ZOOMSCALE 0.75 static int const SCROLL_SIZE = 16; struct _ScrollButton_t { int x; int y; int texIndex; float s1; float t1; float s2; float t2; float s3; float t3; float s4; float t4; }; typedef struct _ScrollButton_t ScrollButtonT; static ScrollButtonT s_buttons[ TextureWidget::ScrollButtonMAX ] = { { -18, -18, 1, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }, // Pan { -52, -18, 0, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, // Left { -35, -18, 0, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, // Right { -18, -35, 0, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }, // Up { -18, -52, 0, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }, // Down }; using std::vector; using std::list; TextureWidget::TextureWidget( QWidget * parent ) : QGLWidget( parent ), m_sClamp( false ), m_tClamp( false ), m_zoom( 1.0 ), m_xCenter( 0.5 ), m_yCenter( 0.5 ), m_model( NULL ), m_materialId( -1 ), m_texture( NULL ), m_glTexture( 0 ), m_scrollTimer( new QTimer() ), m_overlayButton( ScrollButtonMAX ), m_drawMode( DM_Edit ), m_drawVertices( true ), m_solidBackground( false ), m_operation( MouseSelect ), m_scaleKeepAspect( false ), m_scaleFromCenter( false ), m_selecting( false ), m_drawBounding( false ), m_drawRange( false ), m_interactive( false ), m_3d( false ), m_button( 0 ), m_animTimer( new QTimer() ), m_xMin( 0.0 ), m_xMax( 1.0 ), m_yMin( 0.0 ), m_yMax( 1.0 ), m_xRotPoint( 0.5 ), m_yRotPoint( 0.5 ) { connect( m_animTimer, SIGNAL(timeout()), this, SLOT(animationTimeout())); setFocusPolicy( Qt::WheelFocus ); connect( m_scrollTimer, SIGNAL(timeout()), this, SLOT(scrollTimeout())); } TextureWidget::~TextureWidget() { m_animTimer->stop(); delete m_animTimer; m_animTimer = NULL; makeCurrent(); glDeleteTextures( 1, (GLuint *) &m_glTexture ); // Do NOT free m_texture. TextureManager does that. glDeleteTextures( 2, m_scrollTextures ); m_scrollTimer->stop(); delete m_scrollTimer; } void TextureWidget::initializeGL() { // general set-up glEnable( GL_TEXTURE_2D ); setAutoBufferSwap( false ); glShadeModel( GL_SMOOTH ); glDepthFunc( GL_LEQUAL ); glClearColor( 0.80, 0.80, 0.80, 1.0 ); glClearDepth( 1.0f ); // set up overlay arrows QPixmap arrow( arrow_xpm ); QPixmap cross( crosshairrow_xpm ); QImage img; glGenTextures( 2, m_scrollTextures ); img = arrow.toImage(); makeTextureFromImage( img, m_scrollTextures[0] ); img = cross.toImage(); makeTextureFromImage( img, m_scrollTextures[1] ); // set up GL texture glGenTextures( 1, &m_glTexture ); // set up lighting GLfloat ambient[] = { 0.8f, 0.8f, 0.8f, 1.0f }; GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat position[] = { 0.0f, 0.0f, 3.0f, 0.0f }; glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE ); glLightfv( GL_LIGHT0, GL_AMBIENT, ambient ); glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse ); glLightfv( GL_LIGHT0, GL_POSITION, position ); glEnable( GL_LIGHT0 ); glEnable( GL_LIGHTING ); } void TextureWidget::resizeGL( int w, int h ) { if ( h == 0 ) h = 1; m_viewportWidth = w; m_viewportHeight = h; updateViewport(); } void TextureWidget::updateViewport() { m_xMin = m_xCenter - (m_zoom / 2.0); m_xMax = m_xCenter + (m_zoom / 2.0); m_yMin = m_yCenter - (m_zoom / 2.0); m_yMax = m_yCenter + (m_zoom / 2.0); updateGL(); } void TextureWidget::paintGL() { makeCurrent(); paintInternal(); } void TextureWidget::paintOnGlWidget( QGLWidget * w ) { w->makeCurrent(); paintInternal(); } void TextureWidget::paintInternal() { setViewportDraw(); //log_debug( "paintInternal()\n" ); //log_debug( "(%f,%f) %f\n", m_xCenter, m_yCenter, m_zoom ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity( ); glEnable( GL_LIGHTING ); if ( m_texture && !m_solidBackground ) { glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, m_glTexture ); } else { glDisable( GL_TEXTURE_2D ); } glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); if ( m_solidBackground ) { glColor3f( 0.0f, 0.0f, 0.0f ); float fval[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; glMaterialfv( GL_FRONT, GL_AMBIENT, fval ); glMaterialfv( GL_FRONT, GL_DIFFUSE, fval ); glMaterialfv( GL_FRONT, GL_SPECULAR, fval ); glMaterialfv( GL_FRONT, GL_EMISSION, fval ); glMaterialf( GL_FRONT, GL_SHININESS, fval[0] ); } else if ( m_materialId >= 0 ) { glColor3f( 1.0f, 1.0f, 1.0f ); if ( m_model ) { float fval[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; m_model->getTextureAmbient( m_materialId, fval ); glMaterialfv( GL_FRONT, GL_AMBIENT, fval ); m_model->getTextureDiffuse( m_materialId, fval ); glMaterialfv( GL_FRONT, GL_DIFFUSE, fval ); m_model->getTextureSpecular( m_materialId, fval ); glMaterialfv( GL_FRONT, GL_SPECULAR, fval ); m_model->getTextureEmissive( m_materialId, fval ); glMaterialfv( GL_FRONT, GL_EMISSION, fval ); m_model->getTextureShininess( m_materialId, fval[0] ); glMaterialf( GL_FRONT, GL_SHININESS, fval[0] ); } else { float fval[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; glMaterialfv( GL_FRONT, GL_AMBIENT, fval ); fval[0] = fval[1] = fval[2] = 1.0f; glMaterialfv( GL_FRONT, GL_DIFFUSE, fval ); fval[0] = fval[1] = fval[2] = 0.0f; glMaterialfv( GL_FRONT, GL_SPECULAR, fval ); fval[0] = fval[1] = fval[2] = 0.0f; glMaterialfv( GL_FRONT, GL_EMISSION, fval ); glMaterialf( GL_FRONT, GL_SHININESS, 0.0f ); } } else { float fval[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; glMaterialfv( GL_FRONT, GL_AMBIENT, fval ); fval[0] = fval[1] = fval[2] = 1.0f; glMaterialfv( GL_FRONT, GL_DIFFUSE, fval ); fval[0] = fval[1] = fval[2] = 0.0f; glMaterialfv( GL_FRONT, GL_SPECULAR, fval ); fval[0] = fval[1] = fval[2] = 0.0f; glMaterialfv( GL_FRONT, GL_EMISSION, fval ); glMaterialf( GL_FRONT, GL_SHININESS, 0.0f ); if ( m_texture ) { glColor3f( 1.0f, 1.0f, 1.0f ); } else { glDisable( GL_LIGHTING ); glColor3f( 0.0f, 0.0f, 0.0f ); } } if ( m_materialId >= 0 && m_model && m_model->getMaterialType( m_materialId ) == Model::Material::MATTYPE_COLOR ) { GLubyte r = m_model->getMaterialColor( m_materialId, 0 ); GLubyte g = m_model->getMaterialColor( m_materialId, 1 ); GLubyte b = m_model->getMaterialColor( m_materialId, 2 ); glDisable( GL_TEXTURE_2D ); //glDisable( GL_LIGHTING ); glColor3ub( r, g, b ); } if ( m_materialId >= 0 && m_3d ) { glEnable( GL_DEPTH_TEST ); PORT_timeval tv; PORT_gettimeofday( &tv ); int ms = tv.tv_msec + (tv.tv_sec & 7) * 1000; float yRot = (float) ms / 4000.0 * 360.0; float xRot = (float) ms / 8000.0 * 360.0; glTranslatef( 0.0, 0.0, -5.0 ); glRotatef( yRot, 0.0, 1.0, 0.0 ); glRotatef( xRot, 1.0, 0.0, 0.0 ); glBegin( GL_QUADS ); // Front glTexCoord2f( 0.0, 0.0 ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( -1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 0.0 ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( 1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 1.0 ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); glTexCoord2f( 0.0, 1.0 ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 ); // Back glTexCoord2f( 0.0, 0.0 ); glNormal3f( 0.0, 0.0, -1.0 ); glVertex3f( 1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 0.0 ); glNormal3f( 0.0, 0.0, -1.0 ); glVertex3f( -1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 1.0 ); glNormal3f( 0.0, 0.0, -1.0 ); glVertex3f( -1.0, 1.0, -1.0 ); glTexCoord2f( 0.0, 1.0 ); glNormal3f( 0.0, 0.0, -1.0 ); glVertex3f( 1.0, 1.0, -1.0 ); // Left glTexCoord2f( 0.0, 0.0 ); glNormal3f( 1.0, 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 0.0 ); glNormal3f( 1.0, 0.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 1.0 ); glNormal3f( 1.0, 0.0, 0.0 ); glVertex3f( 1.0, 1.0, -1.0 ); glTexCoord2f( 0.0, 1.0 ); glNormal3f( 1.0, 0.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 ); // Right glTexCoord2f( 0.0, 0.0 ); glNormal3f( -1.0, 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 0.0 ); glNormal3f( -1.0, 0.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 1.0 ); glNormal3f( -1.0, 0.0, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 ); glTexCoord2f( 0.0, 1.0 ); glNormal3f( -1.0, 0.0, 0.0 ); glVertex3f( -1.0, 1.0, -1.0 ); // Top glTexCoord2f( 0.0, 0.0 ); glNormal3f( 0.0, 1.0, 0.0 ); glVertex3f( -1.0, 1.0, -1.0 ); glTexCoord2f( 1.0, 0.0 ); glNormal3f( 0.0, 1.0, 0.0 ); glVertex3f( 1.0, 1.0, -1.0 ); glTexCoord2f( 1.0, 1.0 ); glNormal3f( 0.0, 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 ); glTexCoord2f( 0.0, 1.0 ); glNormal3f( 0.0, 1.0, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 ); // Bottom glTexCoord2f( 0.0, 0.0 ); glNormal3f( 0.0, -1.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 0.0 ); glNormal3f( 0.0, -1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 1.0 ); glNormal3f( 0.0, -1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 ); glTexCoord2f( 0.0, 1.0 ); glNormal3f( 0.0, -1.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 ); glEnd(); glDisable( GL_DEPTH_TEST ); } else { glBegin( GL_QUADS ); glTexCoord2f( m_xMin, m_yMin ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( m_xMin, m_yMin, 0.0 ); glTexCoord2f( m_xMax, m_yMin ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( m_xMax, m_yMin, 0.0 ); glTexCoord2f( m_xMax, m_yMax ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( m_xMax, m_yMax, 0.0 ); glTexCoord2f( m_xMin, m_yMax ); glNormal3f( 0.0, 0.0, 1.0 ); glVertex3f( m_xMin, m_yMax, 0.0 ); glEnd(); } //glLoadIdentity( ); glDisable( GL_TEXTURE_2D ); glDisable( GL_LIGHTING ); glColor3f( 1.0, 1.0, 1.0 ); if ( m_operation == MouseRange ) { glColor3f( 0.7, 0.7, 0.7 ); } glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); switch ( m_drawMode ) { case DM_Edit: glBegin( GL_TRIANGLES ); drawTriangles(); glEnd(); break; case DM_Edges: glBegin( GL_TRIANGLES ); drawTriangles(); glEnd(); break; case DM_Filled: glColor3f( 0.0, 0.0, 0.8 ); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); glBegin( GL_TRIANGLES ); drawTriangles(); glEnd(); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); break; case DM_FilledEdges: glColor3f( 0.0, 0.0, 0.8 ); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); glBegin( GL_TRIANGLES ); drawTriangles(); glEnd(); glClear( GL_DEPTH_BUFFER_BIT ); glColor3f( 1.0, 1.0, 1.0 ); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glBegin( GL_TRIANGLES ); drawTriangles(); glEnd(); break; default: log_error( "Unknown draw mode: %d\n", m_drawMode ); break; } // TODO may want to make "draw points" a separate property if ( m_operation == MouseRange ) { glColor3f( 1.0, 1.0, 1.0 ); } // TODO may want to make "draw points" a separate property if ( m_operation != MouseRange || m_drawVertices ) { glPointSize( 3.0 ); glBegin( GL_POINTS ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { for ( unsigned v = 0; v < 3; v++ ) { TextureVertexT * vert = m_vertices[ m_triangles[t]->vertex[v] ]; if ( m_drawMode == DM_Edit && vert->selected ) { glColor3f( 1.0, 0.0, 0.0 ); } else { glColor3f( 1.0, 1.0, 1.0 ); } //glVertex3f( (vert->s - m_xMin) / m_zoom, (vert->t - m_yMin) / m_zoom, -0.5 ); glVertex3f( vert->s, vert->t, -0.5 ); } } glEnd(); } if ( m_drawBounding ) { drawSelectBox(); } if ( m_drawRange ) { drawRangeBox(); } if ( m_operation == MouseRotate ) { drawRotationPoint(); } if ( m_interactive ) { drawOverlay(); } swapBuffers(); } void TextureWidget::drawTriangles() { bool wrapLeft = false; bool wrapRight = false; bool wrapTop = false; bool wrapBottom = false; for ( unsigned t = 0; t < m_triangles.size(); t++ ) { TextureTriangleT * triangle = m_triangles[t]; wrapLeft = false; wrapRight = false; wrapTop = false; wrapBottom = false; for ( unsigned v = 0; v < 3; v++ ) { glVertex3f( m_vertices[ triangle->vertex[v] ]->s, m_vertices[ triangle->vertex[v] ]->t, -0.5 ); if ( m_drawMode != DM_Edit ) { if ( m_vertices[ triangle->vertex[v] ]->s < 0.0 ) { wrapLeft = true; } if ( m_vertices[ triangle->vertex[v] ]->s > 1.0 ) { wrapRight = true; } if ( m_vertices[ triangle->vertex[v] ]->t < 0.0 ) { wrapBottom = true; } if ( m_vertices[ triangle->vertex[v] ]->t > 1.0 ) { wrapTop = true; } } } if ( m_drawMode != DM_Edit ) { if ( wrapLeft ) { for ( unsigned v = 0; v < 3; v++ ) { glVertex3f( m_vertices[ triangle->vertex[v] ]->s + 1.0, m_vertices[ triangle->vertex[v] ]->t, -0.5 ); } } if ( wrapRight ) { for ( unsigned v = 0; v < 3; v++ ) { glVertex3f( m_vertices[ triangle->vertex[v] ]->s - 1.0, m_vertices[ triangle->vertex[v] ]->t, -0.5 ); } } if ( wrapBottom ) { for ( unsigned v = 0; v < 3; v++ ) { glVertex3f( m_vertices[ triangle->vertex[v] ]->s, m_vertices[ triangle->vertex[v] ]->t + 1.0, -0.5 ); } } if ( wrapTop ) { for ( unsigned v = 0; v < 3; v++ ) { glVertex3f( m_vertices[ triangle->vertex[v] ]->s, m_vertices[ triangle->vertex[v] ]->t - 1.0, -0.5 ); } } } } } void TextureWidget::animationTimeout() { updateGL(); } void TextureWidget::setModel( Model * model ) { m_model = model; m_texture = NULL; clearCoordinates(); glDisable( GL_TEXTURE_2D ); } void TextureWidget::set3d( bool o ) { m_3d = o; updateViewport(); if ( o ) { m_animTimer->start( 30 ); } else { m_animTimer->stop(); } } void TextureWidget::setInteractive( bool o ) { m_interactive = o; updateGL(); } void TextureWidget::setTexture( int materialId, Texture * texture ) { m_materialId = materialId; m_texture = texture; m_sClamp = true; m_tClamp = true; if ( m_model ) { m_sClamp = m_model->getTextureSClamp( materialId ); m_tClamp = m_model->getTextureTClamp( materialId ); } if ( m_texture ) { m_zoom = 1.0; m_xCenter = 0.5; m_yCenter = 0.5; updateViewport(); /* m_xMin = m_xCenter - w; m_xMax = m_xCenter + w; m_yMin = m_yCenter - w; m_yMax = m_yCenter + w; */ glBindTexture( GL_TEXTURE_2D, m_glTexture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_sClamp ? GL_CLAMP : GL_REPEAT) ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_tClamp ? GL_CLAMP : GL_REPEAT) ); GLuint format = m_texture->m_format == Texture::FORMAT_RGBA ? GL_RGBA : GL_RGB; gluBuild2DMipmaps( GL_TEXTURE_2D, format, m_texture->m_width, m_texture->m_height, format, GL_UNSIGNED_BYTE, m_texture->m_data ); } else { m_zoom = 1.0; m_xCenter = 0.5; m_yCenter = 0.5; updateViewport(); } resizeGL( this->width(), this->height() ); updateGL(); } int TextureWidget::addVertex( double s, double t ) { int index = m_vertices.size(); TextureVertexT * vert = new TextureVertexT; vert->s = s; vert->t = t; vert->selected = true; m_vertices.push_back( vert ); return index; } int TextureWidget::addTriangle( int v1, int v2, int v3 ) { int vCount = m_vertices.size(); if ( v1 >= 0 && v1 < vCount && v2 >= 0 && v2 < vCount && v3 >= 0 && v3 < vCount ) { int index = m_triangles.size(); TextureTriangleT * triangle = new TextureTriangleT; triangle->vertex[0] = v1; triangle->vertex[1] = v2; triangle->vertex[2] = v3; m_triangles.push_back( triangle ); return index; } return -1; } void TextureWidget::mousePressEvent( QMouseEvent * e ) { if ( m_interactive ) { int w = this->width(); int h = this->height(); m_lastXPos = e->pos().x(); m_lastYPos = e->pos().y(); m_button = m_button | e->button(); int bx = e->pos().x(); int by = h - e->pos().y(); m_overlayButton = ScrollButtonMAX; int sx = 0; int sy = 0; int size = SCROLL_SIZE; for ( int b = 0; m_overlayButton == ScrollButtonMAX && b < ScrollButtonMAX; b++ ) { sx = s_buttons[b].x; sy = s_buttons[b].y; if ( (bx >= w + sx) && (bx <= w + sx + size) && (by >= h + sy) && (by <= h + sy + size) ) { m_overlayButton = (ScrollButtonE) b; switch ( m_overlayButton ) { case ScrollButtonPan: break; case ScrollButtonUp: scrollUp(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; case ScrollButtonDown: scrollDown(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; case ScrollButtonLeft: scrollLeft(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; case ScrollButtonRight: scrollRight(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; default: break; } } } if ( m_overlayButton == ScrollButtonMAX ) { if ( e->button() & Qt::MidButton ) { // We're panning } else { switch ( m_operation ) { case MouseSelect: if ( !( (e->modifiers() & Qt::ShiftModifier) || (e->button() & Qt::RightButton) ) ) { clearSelected(); } m_xSel1 = (m_lastXPos / (double) this->width()) * (m_xMax - m_xMin) + m_xMin; m_ySel1 = (1.0 - (m_lastYPos / (double) this->height())) * (m_yMax - m_yMin) + m_yMin; m_selecting = ( e->button() & Qt::RightButton ) ? false : true; m_drawBounding = true; break; case MouseMove: break; case MouseScale: startScale( (m_lastXPos / (double) this->width()) * (m_xMax - m_xMin) + m_xMin , (1.0 - (m_lastYPos / (double) this->height())) * (m_yMax - m_yMin) + m_yMin ); break; case MouseRotate: { double aspect = (double) this->width() / (double) this->height(); if ( (e->button() & Qt::RightButton) ) { m_xRotPoint = (m_lastXPos / (double) this->width()) * (m_xMax - m_xMin) + m_xMin; m_yRotPoint = (1.0 - (m_lastYPos / (double) this->height())) * (m_yMax - m_yMin) + m_yMin; } else { m_xRotStart = (m_lastXPos / (double) this->width()) * (m_xMax - m_xMin) + m_xMin; m_yRotStart = (1.0 - (m_lastYPos / (double) this->height())) * (m_yMax - m_yMin) + m_yMin; m_xRotStart -= m_xRotPoint; m_yRotStart -= m_yRotPoint; double opposite = m_yRotStart; double adjacent = m_xRotStart * aspect; if ( adjacent < 0.0001 && adjacent > -0.0001 ) { adjacent = (adjacent >= 0 ) ? 0.0001 : -0.0001; } double angle = atan( opposite / adjacent ); float quad = PIOVER180 * 90; if ( adjacent < 0 ) { if ( opposite < 0 ) { angle = -(quad) - ( (quad) - angle ); } else { angle = (quad) + ( (quad) + angle ); } } m_startAngle = angle; } freeRotateVertices(); for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->selected ) { RotateVertexT * rot = new RotateVertexT; rot->x = (m_vertices[v]->s - m_xRotPoint) * aspect; rot->y = m_vertices[v]->t - m_yRotPoint; rot->v = v; m_rotateVertices.push_back( rot ); } } updateGL(); } break; case MouseRange: { m_dragAll = false; m_dragTop = false; m_dragBottom = false; m_dragLeft = false; m_dragRight = false; double windowX = getWindowXCoord( m_lastXPos ); double windowY = getWindowYCoord( m_lastYPos ); getDragDirections( windowX, windowY, m_dragAll, m_dragTop, m_dragBottom, m_dragLeft, m_dragRight ); setDragCursor( m_dragAll, m_dragTop, m_dragBottom, m_dragLeft, m_dragRight ); } break; default: log_error( "Unknown mouse operation: %d\n", m_operation ); break; } } } } } void TextureWidget::mouseReleaseEvent( QMouseEvent * e ) { if ( m_interactive ) { if ( m_overlayButton == ScrollButtonMAX ) { int x = e->pos().x(); int y = e->pos().y(); if ( e->button() & Qt::MidButton ) { // We're panning } else { switch ( m_operation ) { case MouseSelect: m_drawBounding = false; updateSelectRegion( (x / (double) this->width()) * (m_xMax - m_xMin) + m_xMin, (1.0 - (y / (double) this->height())) * (m_yMax - m_yMin) + m_yMin ); selectDone(); break; case MouseMove: moveSelectedVertices( ((x - m_lastXPos) / (double) this->width()) * (m_xMax - m_xMin), (-(y - m_lastYPos) / (double) this->height()) * (m_yMax - m_yMin) ); emit updateCoordinatesSignal(); emit updateCoordinatesDoneSignal(); break; case MouseRotate: // Nothing to do here emit updateCoordinatesDoneSignal(); break; case MouseScale: // Nothing to do here emit updateCoordinatesDoneSignal(); break; case MouseRange: if ( m_button & Qt::LeftButton ) { if ( m_dragAll || m_dragTop || m_dragBottom || m_dragLeft || m_dragRight ) { emit updateRangeDoneSignal(); } } else { if ( m_dragAll ) { emit updateSeamDoneSignal(); } } break; default: log_error( "Unknown mouse operation: %d\n", m_operation ); break; } } } else { m_overlayButton = ScrollButtonMAX; m_scrollTimer->stop(); } m_button = m_button & ~(e->button()); } } void TextureWidget::mouseMoveEvent( QMouseEvent * e ) { if ( m_interactive ) { int x = e->pos().x(); int y = e->pos().y(); if ( m_overlayButton == ScrollButtonMAX ) { if ( m_button != 0 ) { if ( m_button & Qt::MidButton ) { double xDiff = (double) -(x - m_lastXPos); double yDiff = (double) (y - m_lastYPos); xDiff = xDiff / (double) m_viewportWidth; yDiff = yDiff / (double) m_viewportHeight; xDiff *= m_zoom; yDiff *= m_zoom; m_xCenter += xDiff; m_yCenter += yDiff; m_xMin += xDiff; m_yMin += yDiff; m_xMax += xDiff; m_yMax += yDiff; updateViewport(); } else { switch ( m_operation ) { case MouseSelect: /* updateSelectRegion( x / (double) this->width(), 1.0 - (y / (double) this->height()) ); */ updateSelectRegion( (x / (double) this->width()) * m_zoom + m_xMin, (1.0 - (y / (double) this->height())) * m_zoom + m_yMin ); break; case MouseMove: moveSelectedVertices( ((x - m_lastXPos) / (double) this->width()) * m_zoom, (-(y - m_lastYPos) / (double) this->height()) * m_zoom); emit updateCoordinatesSignal(); break; case MouseRotate: { double xNew = (x / (double) this->width()) * (m_xMax - m_xMin) + m_xMin; double yNew = (1.0 - (y / (double) this->height())) * (m_yMax - m_yMin) + m_yMin; xNew -= m_xRotPoint; yNew -= m_yRotPoint; double aspect = (double) this->width() / (double) this->height(); double opposite = yNew; double adjacent = xNew * aspect; if ( adjacent < 0.0001 && adjacent > -0.0001 ) { adjacent = (adjacent >= 0 ) ? 0.0001 : -0.0001; } double angle = atan( opposite / adjacent ); float quad = PIOVER180 * 90; if ( adjacent < 0 ) { if ( opposite < 0 ) { angle = -(quad) - ( (quad) - angle ); } else { angle = (quad) + ( (quad) + angle ); } } rotateSelectedVertices( angle - m_startAngle ); emit updateCoordinatesSignal(); } break; case MouseScale: scaleSelectedVertices( (x / (double) this->width()) * m_zoom + m_xMin, (1.0 - (y / (double) this->height())) * m_zoom + m_yMin ); emit updateCoordinatesSignal(); break; case MouseRange: if ( m_button & Qt::LeftButton ) { double xThen = getWindowXCoord( m_lastXPos ); double xNow = getWindowXCoord( x ); double yThen = getWindowYCoord( m_lastYPos ); double yNow = getWindowYCoord( y ); double xDiff = xNow - xThen; double yDiff = yNow - yThen; if ( m_dragLeft || m_dragAll ) { m_xRangeMin += xDiff; if ( m_xRangeMin > m_xRangeMax ) { m_xRangeMax = m_xRangeMin; } } if ( m_dragRight || m_dragAll ) { m_xRangeMax += xDiff; if ( m_xRangeMax < m_xRangeMin ) { m_xRangeMin = m_xRangeMax; } } if ( m_dragBottom || m_dragAll ) { m_yRangeMin += yDiff; if ( m_yRangeMin > m_yRangeMax ) { m_yRangeMax = m_yRangeMin; } } if ( m_dragTop || m_dragAll ) { m_yRangeMax += yDiff; if ( m_yRangeMax < m_yRangeMin ) { m_yRangeMin = m_yRangeMax; } } if ( m_dragAll || m_dragTop || m_dragBottom || m_dragLeft || m_dragRight ) { emit updateRangeSignal(); } } else { if ( m_dragAll ) { double xThen = getWindowXCoord( m_lastXPos ); double xNow = getWindowXCoord( x ); double yThen = getWindowYCoord( m_lastYPos ); double yNow = getWindowYCoord( y ); double xDiff = xNow - xThen; double yDiff = yNow - yThen; xDiff *= -(2 * PI); yDiff *= -(2 * PI); emit updateSeamSignal( xDiff, yDiff ); } } break; default: log_error( "Unknown mouse operation: %d\n", m_operation ); break; } } } else { updateCursorShape( x, y ); } } else { if ( m_overlayButton == ScrollButtonPan ) { double xDiff = (double) -(x - m_lastXPos); double yDiff = (double) (y - m_lastYPos); xDiff = xDiff / (double) m_viewportWidth; yDiff = yDiff / (double) m_viewportHeight; xDiff *= m_zoom; yDiff *= m_zoom; m_xCenter += xDiff; m_yCenter += yDiff; m_xMin += xDiff; m_yMin += yDiff; m_xMax += xDiff; m_yMax += yDiff; updateViewport(); } } m_lastXPos = x; m_lastYPos = y; } } void TextureWidget::wheelEvent( QWheelEvent * e ) { if ( m_interactive ) { if ( e->delta() > 0 ) { zoomIn(); } else { zoomOut(); } } } void TextureWidget::keyPressEvent( QKeyEvent * e ) { if ( m_interactive ) { switch ( e->key() ) { case Qt::Key_Home: { if ( (e->modifiers() & Qt::ShiftModifier) == Qt::ShiftModifier ) { if ( m_drawMode == DM_Edit ) { if ( m_operation == MouseRange ) { m_xCenter = (m_xRangeMax - m_xRangeMin) / 2.0 + m_xRangeMin; m_yCenter = (m_yRangeMax - m_yRangeMin) / 2.0 + m_yRangeMin; double xzoom = m_xRangeMax - m_xRangeMin; double yzoom = m_yRangeMax - m_yRangeMin; m_zoom = (xzoom > yzoom) ? xzoom : yzoom; m_zoom *= 1.10; updateViewport(); } else { bool first = true; double xMin = 0.0; double xMax = 0.0; double yMin = 0.0; double yMax = 0.0; size_t vcount = m_vertices.size(); for ( size_t v = 1; v < vcount; v++ ) { if ( m_vertices[v]->selected ) { if ( first ) { xMin = m_vertices[v]->s; yMin = m_vertices[v]->t; first = false; } else { if ( m_vertices[v]->s < xMin ) xMin = m_vertices[v]->s; if ( m_vertices[v]->s > xMax ) xMax = m_vertices[v]->s; if ( m_vertices[v]->t < yMin ) yMin = m_vertices[v]->t; if ( m_vertices[v]->t > yMax ) yMax = m_vertices[v]->t; } } } if ( !first ) { m_xCenter = (xMax - xMin) / 2.0 + xMin; m_yCenter = (yMax - yMin) / 2.0 + yMin; double xzoom = xMax - xMin; double yzoom = yMax - yMin; m_zoom = (xzoom > yzoom) ? xzoom : yzoom; m_zoom *= 1.10; updateViewport(); } } } } else { m_xCenter = 0.5; m_yCenter = 0.5; m_zoom = 1.0; updateViewport(); } } break; case Qt::Key_Equal: case Qt::Key_Plus: { zoomIn(); } break; case Qt::Key_Minus: case Qt::Key_Underscore: { zoomOut(); } break; case Qt::Key_0: m_xCenter = 0.5; m_yCenter = 0.5; updateViewport(); break; case Qt::Key_Up: scrollUp(); break; case Qt::Key_Down: scrollDown(); break; case Qt::Key_Left: scrollLeft(); break; case Qt::Key_Right: scrollRight(); break; default: QGLWidget::keyPressEvent( e ); break; } } else { QGLWidget::keyPressEvent( e ); } } void TextureWidget::zoomIn() { if ( m_interactive ) { if ( (m_zoom / VP_ZOOMSCALE) > 0.0001 ) { m_zoom *= (VP_ZOOMSCALE); } QString zoomStr; zoomStr.sprintf( "%f", (float) m_zoom ); emit zoomLevelChanged( zoomStr ); updateViewport(); } } void TextureWidget::zoomOut() { if ( m_interactive ) { if ( (m_zoom / VP_ZOOMSCALE) < 250000 ) { m_zoom /= VP_ZOOMSCALE; } QString zoomStr; zoomStr.sprintf( "%f", (float) m_zoom ); emit zoomLevelChanged( zoomStr ); updateViewport(); } } void TextureWidget::setZoomLevel( double zoom ) { if ( m_interactive ) { m_zoom = zoom; updateViewport(); } } void TextureWidget::scrollTimeout() { switch ( m_overlayButton ) { case ScrollButtonUp: scrollUp(); break; case ScrollButtonDown: scrollDown(); break; case ScrollButtonLeft: scrollLeft(); break; case ScrollButtonRight: scrollRight(); break; default: m_scrollTimer->stop(); return; } m_scrollTimer->setSingleShot( false ); m_scrollTimer->start( 100 ); } void TextureWidget::scrollUp() { m_yCenter += m_zoom * 0.10; updateViewport(); } void TextureWidget::scrollDown() { m_yCenter -= m_zoom * 0.10; updateViewport(); } void TextureWidget::scrollLeft() { m_xCenter -= m_zoom * 0.10; updateViewport(); } void TextureWidget::scrollRight() { m_xCenter += m_zoom * 0.10; updateViewport(); } void TextureWidget::moveSelectedVertices( double x, double y ) { for ( unsigned t = 0; t < m_vertices.size(); t++ ) { if ( m_vertices[t]->selected ) { m_vertices[t]->s += x; m_vertices[t]->t += y; } } updateGL(); } void TextureWidget::updateSelectRegion( double x, double y ) { m_xSel2 = x; m_ySel2 = y; updateGL(); } void TextureWidget::setViewportDraw() { glViewport( 0, 0, ( GLint ) m_viewportWidth, ( GLint ) m_viewportHeight ); glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); GLfloat ratio = ( GLfloat ) m_viewportWidth / ( GLfloat ) m_viewportHeight; glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); if ( m_3d ) { gluPerspective( 45.0f, ratio, 0.01, 30.0 ); } else { glOrtho( m_xMin, m_xMax, m_yMin, m_yMax, -1.0, 1.0 ); } glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); } void TextureWidget::setViewportOverlay() { glViewport( 0, 0, ( GLint ) m_viewportWidth, ( GLint ) m_viewportHeight ); glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); glOrtho( 0, this->width(), 0, this->height(), -1.0, 1.0 ); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); } void TextureWidget::drawOverlay() { setViewportOverlay(); glDisable( GL_LIGHTING ); glColor3f( 1.0f, 1.0f, 1.0f ); glEnable( GL_TEXTURE_2D ); int w = this->width(); int h = this->height(); int sx = 0; int sy = 0; int size = SCROLL_SIZE; for ( int b = 0; b < ScrollButtonMAX; b++ ) { ScrollButtonT * sbt = &s_buttons[b]; sx = sbt->x; sy = sbt->y; glBindTexture( GL_TEXTURE_2D, m_scrollTextures[ sbt->texIndex ] ); glBegin( GL_QUADS ); glTexCoord2f( sbt->s1, sbt->t1 ); glVertex3f( w + sx, h + sy, 0 ); glTexCoord2f( sbt->s2, sbt->t2 ); glVertex3f( w + sx + size, h + sy, 0 ); glTexCoord2f( sbt->s3, sbt->t3 ); glVertex3f( w + sx + size, h + sy + size, 0 ); glTexCoord2f( sbt->s4, sbt->t4 ); glVertex3f( w + sx, h + sy + size, 0 ); glEnd(); } glDisable( GL_TEXTURE_2D ); } void TextureWidget::makeTextureFromImage( const QImage & i, GLuint & t ) { glBindTexture( GL_TEXTURE_2D, t ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); int w = i.width(); int h = i.height(); unsigned pixelCount = w * i.height(); uint8_t * data = new uint8_t[ pixelCount * 3 ]; for ( int y = 0; y < h; y ++ ) { for ( int x = 0; x < w; x++ ) { QRgb p = i.pixel( x, h - y - 1 ); data[ ((y * w + x)*3) + 0 ] = qRed( p ); data[ ((y * w + x)*3) + 1 ] = qGreen( p ); data[ ((y * w + x)*3) + 2 ] = qBlue( p ); } } gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE, data ); delete data; } void TextureWidget::selectDone() { if ( m_xSel1 > m_xSel2 ) { double temp = m_xSel2; m_xSel2 = m_xSel1; m_xSel1 = temp; } if ( m_ySel1 > m_ySel2 ) { double temp = m_ySel2; m_ySel2 = m_ySel1; m_ySel1 = temp; } for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->s >= m_xSel1 && m_vertices[v]->s <= m_xSel2 && m_vertices[v]->t >= m_ySel1 && m_vertices[v]->t <= m_ySel2 ) { m_vertices[v]->selected = m_selecting; } } updateGL(); } void TextureWidget::setTextureCount( unsigned c ) { setTexture( m_materialId, m_texture ); } void TextureWidget::setMouseOperation( MouseOperationE op ) { m_operation = op; m_drawRange = false; if ( op == MouseRange ) { m_drawRange = true; } } void TextureWidget::setDrawMode( DrawModeE dm ) { m_drawMode = dm; } void TextureWidget::drawSelectBox() { glEnable( GL_COLOR_LOGIC_OP ); glColor3f( 1.0, 1.0, 1.0 ); glLogicOp( GL_XOR ); glBegin( GL_LINES ); glVertex3f( m_xSel1, m_ySel1, -0.75 ); glVertex3f( m_xSel1, m_ySel2, -0.75 ); glVertex3f( m_xSel1, m_ySel2, -0.75 ); glVertex3f( m_xSel2, m_ySel2, -0.75 ); glVertex3f( m_xSel2, m_ySel2, -0.75 ); glVertex3f( m_xSel2, m_ySel1, -0.75 ); glVertex3f( m_xSel2, m_ySel1, -0.75 ); glVertex3f( m_xSel1, m_ySel1, -0.75 ); glEnd(); glLogicOp( GL_COPY ); glDisable( GL_LOGIC_OP ); } void TextureWidget::drawRangeBox() { glLogicOp( GL_COPY ); glDisable( GL_LOGIC_OP ); glColor3f( 1.0, 1.0, 1.0 ); glBegin( GL_LINES ); glVertex3f( m_xRangeMin, m_yRangeMin, -0.95 ); glVertex3f( m_xRangeMin, m_yRangeMax, -0.95 ); glVertex3f( m_xRangeMin, m_yRangeMax, -0.95 ); glVertex3f( m_xRangeMax, m_yRangeMax, -0.95 ); glVertex3f( m_xRangeMax, m_yRangeMax, -0.95 ); glVertex3f( m_xRangeMax, m_yRangeMin, -0.95 ); glVertex3f( m_xRangeMax, m_yRangeMin, -0.95 ); glVertex3f( m_xRangeMin, m_yRangeMin, -0.95 ); glEnd(); } void TextureWidget::drawRotationPoint() { glLogicOp( GL_COPY ); glDisable( GL_LOGIC_OP ); glColor3f( 0.0, 1.0, 0.0 ); glBegin( GL_LINES ); double offset = m_zoom * 0.04; double aspect = (double) this->width() / (double) this->height(); double xoff = offset / aspect; double yoff = offset; glVertex3f( m_xRotPoint - xoff, m_yRotPoint + 0.0, -0.95 ); glVertex3f( m_xRotPoint + 0.0, m_yRotPoint - yoff, -0.95 ); glVertex3f( m_xRotPoint + 0.0, m_yRotPoint - yoff, -0.95 ); glVertex3f( m_xRotPoint + xoff, m_yRotPoint + 0.0, -0.95 ); glVertex3f( m_xRotPoint + xoff, m_yRotPoint + 0.0, -0.95 ); glVertex3f( m_xRotPoint + 0.0, m_yRotPoint + yoff, -0.95 ); glVertex3f( m_xRotPoint + 0.0, m_yRotPoint + yoff, -0.95 ); glVertex3f( m_xRotPoint - xoff, m_yRotPoint + 0.0, -0.95 ); glEnd(); } void TextureWidget::clearSelected() { for ( unsigned v = 0; v < m_vertices.size(); v++ ) { m_vertices[v]->selected = false; } } double TextureWidget::getWindowXCoord( int x ) { return (x / (double) m_viewportWidth) * m_zoom + m_xMin; } double TextureWidget::getWindowYCoord( int y ) { return ((m_viewportHeight - y) / (double) m_viewportHeight) * m_zoom + m_yMin; } void TextureWidget::updateCursorShape( int x, int y ) { if ( m_interactive ) { int w = this->width(); int h = this->height(); int sx = 0; int sy = 0; int size = SCROLL_SIZE; int bx = x; int by = h - y; ScrollButtonE button = ScrollButtonMAX; for ( int b = 0; button == ScrollButtonMAX && b < ScrollButtonMAX; b++ ) { sx = s_buttons[b].x; sy = s_buttons[b].y; if ( (bx >= w + sx) && (bx <= w + sx + size) && (by >= h + sy) && (by <= h + sy + size) ) { button = (ScrollButtonE) b; } } switch ( button ) { case ScrollButtonPan: case ScrollButtonUp: case ScrollButtonDown: case ScrollButtonLeft: case ScrollButtonRight: break; default: break; } if ( button == ScrollButtonMAX ) { if ( m_operation == MouseRange ) { bool dragAll = false; bool dragTop = false; bool dragBottom = false; bool dragLeft = false; bool dragRight = false; double windowX = getWindowXCoord( x ); double windowY = getWindowYCoord( y ); getDragDirections( windowX, windowY, dragAll, dragTop, dragBottom, dragLeft, dragRight ); setDragCursor( dragAll, dragTop, dragBottom, dragLeft, dragRight ); return; } } } setDragCursor( false, false, false, false, false ); } void TextureWidget::getDragDirections( double windowX, double windowY, bool & dragAll, bool & dragTop, bool & dragBottom, bool & dragLeft, bool & dragRight ) { dragAll = false; dragTop = false; dragBottom = false; dragLeft = false; dragRight = false; double prox = (6.0 / m_viewportWidth) * m_zoom; if ( (windowX >= (m_xRangeMin - prox)) && (windowX <= (m_xRangeMax + prox)) && (windowY >= (m_yRangeMin - prox)) && (windowY <= (m_yRangeMax + prox)) ) { if ( fabs(m_xRangeMin - windowX) <= prox ) { dragLeft = true; } if ( fabs(m_xRangeMax - windowX) <= prox ) { dragRight = true; } if ( fabs(m_yRangeMin - windowY) <= prox ) { dragBottom = true; } if ( fabs(m_yRangeMax - windowY) <= prox ) { dragTop = true; } if ( dragLeft && dragRight ) { // The min and max are very close together, don't drag // both at one time. if ( windowX < m_xRangeMin ) { dragRight = false; } else if ( windowX > m_xRangeMax ) { dragLeft = false; } else { // We're in-between, don't drag either (top/bottom still okay) dragLeft = false; dragRight = false; } } if ( dragTop && dragBottom ) { // The min and max are very close together, don't drag // both at one time. if ( windowY < m_yRangeMin ) { dragTop = false; } else if ( windowY > m_yRangeMax ) { dragBottom = false; } else { // We're in-between, don't drag either (left/right still okay) dragTop = false; dragBottom = false; } } if ( !dragTop && !dragBottom && !dragLeft && !dragRight ) { if ( (windowX > m_xRangeMin && windowX < m_xRangeMax) && (windowY > m_yRangeMin && windowY < m_yRangeMax ) ) { dragAll = true; } } } } void TextureWidget::setDragCursor( bool dragAll, bool dragTop, bool dragBottom, bool dragLeft, bool dragRight ) { if ( !m_interactive ) { setCursor( QCursor( Qt::ArrowCursor ) ); } else if ( (dragLeft && dragTop) || (dragRight && dragBottom) ) { setCursor( QCursor( Qt::SizeFDiagCursor ) ); } else if ( (dragLeft && dragBottom) || (dragRight && dragTop) ) { setCursor( QCursor( Qt::SizeBDiagCursor ) ); } else if ( dragLeft || dragRight ) { setCursor( QCursor( Qt::SizeHorCursor ) ); } else if ( dragTop || dragBottom ) { setCursor( QCursor( Qt::SizeVerCursor ) ); } else if ( dragAll ) { setCursor( QCursor( Qt::SizeAllCursor ) ); } else { setCursor( QCursor( Qt::ArrowCursor ) ); } } void TextureWidget::clearCoordinates() { while ( m_triangles.size() ) { delete m_triangles.back(); m_triangles.pop_back(); } while ( m_vertices.size() ) { delete m_vertices.back(); m_vertices.pop_back(); } freeRotateVertices(); } void TextureWidget::getCoordinates( int tri, float * s, float * t ) { if ( !t || !s || tri >= (signed) m_triangles.size() ) { return; } for ( int v = 0; v < 3; v++ ) { s[v] = m_vertices[ m_triangles[ tri ]->vertex[v] ]->s; t[v] = m_vertices[ m_triangles[ tri ]->vertex[v] ]->t; } } void TextureWidget::setRange( double xMin, double yMin, double xMax, double yMax ) { m_xRangeMin = xMin; m_yRangeMin = yMin; m_xRangeMax = xMax; m_yRangeMax = yMax; } void TextureWidget::getRange( double & xMin, double & yMin, double & xMax, double & yMax ) { xMin = m_xRangeMin; yMin = m_yRangeMin; xMax = m_xRangeMax; yMax = m_yRangeMax; } void TextureWidget::startScale( double x, double y ) { m_scaleList.clear(); bool first = true; double minX = 0; double minY = 0; double maxX = 0; double maxY = 0; for ( unsigned t = 0; t < m_vertices.size(); t++ ) { if ( m_vertices[t]->selected ) { // update range if ( first ) { minX = m_vertices[t]->s; minY = m_vertices[t]->t; maxX = m_vertices[t]->s; maxY = m_vertices[t]->t; first = false; } else { if ( m_vertices[t]->s < minX ) { minX = m_vertices[t]->s; }; if ( m_vertices[t]->t < minY ) { minY = m_vertices[t]->t; }; if ( m_vertices[t]->s > maxX ) { maxX = m_vertices[t]->s; }; if ( m_vertices[t]->t > maxY ) { maxY = m_vertices[t]->t; }; } ScaleVerticesT sv; sv.index = t; sv.x = m_vertices[t]->s; sv.y = m_vertices[t]->t; m_scaleList.push_back( sv ); } } if ( m_scaleFromCenter ) { m_centerX = (maxX - minX) / 2.0 + minX; m_centerY = (maxY - minY) / 2.0 + minY; m_startLengthX = fabs( m_centerX - x ); m_startLengthY = fabs( m_centerY - y ); } else { double minmin = distance( x, y, minX, minY ); double minmax = distance( x, y, minX, maxY ); double maxmin = distance( x, y, maxX, minY ); double maxmax = distance( x, y, maxX, maxY ); if ( minmin > minmax ) { if ( minmin > maxmin ) { if ( minmin > maxmax ) { m_farX = minX; m_farY = minY; } else { m_farX = maxX; m_farY = maxY; } } else // maxmin > minmin { if ( maxmin > maxmax ) { m_farX = maxX; m_farY = minY; } else { m_farX = maxX; m_farY = maxY; } } } else // minmax > minmin { if ( minmax > maxmin ) { if ( minmax > maxmax ) { m_farX = minX; m_farY = maxY; } else { m_farX = maxX; m_farY = maxY; } } else // maxmin > minmax { if ( maxmin > maxmax ) { m_farX = maxX; m_farY = minY; } else { m_farX = maxX; m_farY = maxY; } } } m_startLengthX = fabs( x - m_farX ); m_startLengthY = fabs( y - m_farY ); } } void TextureWidget::rotateSelectedVertices( double angle ) { Matrix m; Vector rot; rot[0] = 0.0; rot[1] = 0.0; rot[2] = angle; m.setRotation( rot ); double aspect = (double) this->width() / (double) this->height(); unsigned vcount = m_rotateVertices.size(); for ( unsigned v = 0; v < vcount; v++ ) { Vector vec; vec[0] = m_rotateVertices[v]->x; vec[1] = m_rotateVertices[v]->y; m.apply3( vec ); unsigned index = m_rotateVertices[v]->v; m_vertices[index]->s = (vec[0] / aspect)+ m_xRotPoint; m_vertices[index]->t = vec[1] + m_yRotPoint; } updateGL(); } void TextureWidget::scaleSelectedVertices( double x, double y ) { double spX = m_scaleFromCenter ? m_centerX : m_farX; double spY = m_scaleFromCenter ? m_centerY : m_farY; double lengthX = fabs( x - spX ); double lengthY = fabs( y - spY ); ScaleVerticesList::iterator it; for( it = m_scaleList.begin(); it != m_scaleList.end(); it++ ) { double x = (*it).x; double y = (*it).y; x -= spX; y -= spY; double xper = (lengthX / m_startLengthX); if ( m_startLengthX <= 0.00006 ) { xper = 1.0; } double yper = (lengthY / m_startLengthY); if ( m_startLengthY <= 0.00006 ) { yper = 1.0; } if ( m_scaleKeepAspect ) { if ( xper > yper ) { yper = xper; } else { xper = yper; } } x *= xper; y *= yper; x += spX; y += spY; m_vertices[(*it).index]->s = x; m_vertices[(*it).index]->t = y; } updateGL(); } void TextureWidget::freeRotateVertices() { while ( m_rotateVertices.size() ) { delete m_rotateVertices.back(); m_rotateVertices.pop_back(); } } double TextureWidget::distance( const double & x1, const double & y1, const double & x2, const double & y2 ) { double xDiff = x2 - x1; double yDiff = y2 - y1; return sqrt( xDiff*xDiff + yDiff*yDiff ); } double TextureWidget::max( const double & a, const double & b ) { return ( a > b ) ? a : b; } mm3d-1.3.7/src/depui/modelviewport.cc0000644000175000017500000023627110751176434014432 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "toolbox.h" #include "tool.h" #include "glmath.h" #include "decalmgr.h" #include "decal.h" #include "log.h" #include "modelstatus.h" #include "texmgr.h" #include "modelviewport.h" #include "3dmprefs.h" #include "mm3dport.h" #include "pixmap/arrow.xpm" #include "pixmap/crosshairrow.xpm" #include #include #include #include #include #include #include #include #include #define NEWVIEWPORT #define VP_ZOOMSCALE 0.75 #define MM3D_ENABLEALPHA static int const SCROLL_SIZE = 16; struct _ScrollButton_t { int x; int y; int texIndex; float s1; float t1; float s2; float t2; float s3; float t3; float s4; float t4; }; typedef struct _ScrollButton_t ScrollButtonT; static ScrollButtonT s_buttons[ ModelViewport::ScrollButtonMAX ] = { { -18, -18, 1, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }, // Pan { -52, -18, 0, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }, // Left { -35, -18, 0, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, // Right { -18, -35, 0, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }, // Up { -18, -52, 0, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }, // Down }; static Matrix s_mat; ModelViewport::ModelViewport( QWidget * parent ) : QGLWidget( parent ), m_model( NULL ), m_operation( MO_None ), m_activeButton( Qt::NoButton ), m_viewDirection( ViewFront ), m_centerX( 0.0 ), m_centerY( 0.0 ), m_centerZ( 0.0 ), m_rotX( 0.0 ), m_rotY( 0.0 ), m_rotZ( 0.0 ), m_zoomLevel( 32.0 ), m_far( 10000.0 ), m_near( 1.0 ), m_farOrtho( 1000000.0 ), m_nearOrtho( 0.001 ), m_viewportWidth( 0 ), m_viewportHeight( 0 ), m_scrollTimer( new QTimer() ), m_overlayButton( ScrollButtonMAX ), m_capture( false ), m_texturesLoaded( false ), m_viewOptions( ViewTexture ), m_toolbox( NULL ) { // Default preferences m_arcballPoint[0] = 0.0; m_arcballPoint[1] = 0.0; m_arcballPoint[2] = 0.0; m_scrollTimer->setSingleShot( true ); g_prefs.setDefault( "ui_grid_inc", 4.0 ); g_prefs.setDefault( "ui_3dgrid_inc", 4.0 ); g_prefs.setDefault( "ui_3dgrid_count", 6 ); g_prefs.setDefault( "ui_3dgrid_xy", 0 ); g_prefs.setDefault( "ui_3dgrid_xz", 1 ); g_prefs.setDefault( "ui_3dgrid_yz", 0 ); setAutoBufferSwap( false ); setFocusPolicy( Qt::WheelFocus ); setMinimumSize( 220, 180 ); double rot[3] = { 45 * PIOVER180, 0, 0 }; s_mat.setRotation( rot ); m_backColor.setRgb( 130, 200, 200 ); setAcceptDrops( true ); setMouseTracking( true ); QPixmap arrow( arrow_xpm ); QPixmap cross( crosshairrow_xpm ); QImage img; makeCurrent(); glGenTextures( 2, m_scrollTextures ); img = arrow.toImage(); makeTextureFromImage( img, m_scrollTextures[0] ); img = cross.toImage(); makeTextureFromImage( img, m_scrollTextures[1] ); connect( m_scrollTimer, SIGNAL(timeout()), this, SLOT(scrollTimeout())); } ModelViewport::~ModelViewport() { log_debug( "deleting model viewport\n" ); makeCurrent(); glDeleteTextures( 1, &m_backgroundTexture ); glDeleteTextures( 2, m_scrollTextures ); freeTextures(); delete m_scrollTimer; } void ModelViewport::freeTextures() { log_debug( "freeing texture for viewport\n" ); makeCurrent(); if ( m_model ) { m_model->removeContext( static_cast( this ) ); } } void ModelViewport::initializeGL() { glShadeModel( GL_SMOOTH ); glClearColor( m_backColor.red() / 256.0, m_backColor.green() / 256.0, m_backColor.blue() / 256.0, 1.0f ); glClearDepth( 1.0f ); glEnable( GL_DEPTH_TEST ); glDepthFunc( GL_LEQUAL ); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); { GLfloat ambient[] = { 0.8f, 0.8f, 0.8f, 1.0f }; GLfloat diffuse[] = { 0.9f, 0.9f, 0.9f, 1.0f }; GLfloat position[] = { 0.0f, 0.0f, 1.0f, 0.0f }; glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE ); glLightfv( GL_LIGHT0, GL_AMBIENT, ambient ); glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse ); glLightfv( GL_LIGHT0, GL_POSITION, position ); //glEnable( GL_LIGHT0 ); } { GLfloat ambient[] = { 0.8f, 0.4f, 0.4f, 1.0f }; GLfloat diffuse[] = { 0.9f, 0.5f, 0.5f, 1.0f }; GLfloat position[] = { 0.0f, 0.0f, 1.0f, 0.0f }; glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE ); glLightfv( GL_LIGHT1, GL_AMBIENT, ambient ); glLightfv( GL_LIGHT1, GL_DIFFUSE, diffuse ); glLightfv( GL_LIGHT1, GL_POSITION, position ); //glEnable( GL_LIGHT1 ); } { GLint texSize = 0; glGetIntegerv( GL_MAX_TEXTURE_SIZE, &texSize ); log_debug( "max texture size is %dx%d\n", texSize, texSize ); } glGenTextures( 1, &m_backgroundTexture ); checkGlErrors(); #ifdef MM3D_ENABLEALPHA glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if ( ! glIsEnabled( GL_BLEND) ) { log_warning( "alpha not supported\n" ); glDisable( GL_BLEND ); glGetError(); // clear errors } #endif // MM3D_ENABLEALPHA } void ModelViewport::resizeGL( int w, int h ) { if ( h == 0 ) { h = 1; } m_viewportWidth = w; m_viewportHeight = h; adjustViewport(); } void ModelViewport::paintGL() { //LOG_PROFILE(); if ( m_inOverlay ) { setViewportDraw(); } if ( m_capture ) { glClearColor( 130.0 / 256.0, 200.0 / 256.0, 200.0 / 256.0, 1.0f ); } float viewPoint[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; if ( m_viewDirection == ViewPerspective || m_viewDirection == ViewOrtho ) { glEnable( GL_LIGHT0 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //if ( m_viewDirection == ViewPerspective ) { glLoadIdentity( ); } #ifdef NEWVIEWPORT viewPoint[0] = m_arcballPoint[0]; // m_centerX; viewPoint[1] = m_arcballPoint[1]; // m_centerY; viewPoint[2] = m_arcballPoint[2] + (m_zoomLevel * 2.0); if ( m_viewDirection == ViewPerspective ) { glTranslatef( -viewPoint[0], -viewPoint[1], -viewPoint[2] ); } else { glTranslatef( 0.0, 0.0, -m_farOrtho / 2.0 ); } glRotatef( m_rotZ, 0.0, 0.0, 1.0); glRotatef( m_rotY, 0.0, 1.0, 0.0); glRotatef( m_rotX, 1.0, 0.0, 0.0); #else viewPoint[0] = m_centerX; viewPoint[1] = m_centerY; viewPoint[2] = (m_zoomLevel * 2.0); glTranslatef( -viewPoint[0], -viewPoint[1], -viewPoint[2] ); glRotatef( m_rotZ, 0.0, 0.0, 1.0); glRotatef( m_rotY, 0.0, 1.0, 0.0); glRotatef( m_rotX, 1.0, 0.0, 0.0); #endif // NEWVIEWPORT Matrix m; m.setRotationInDegrees( 0.0f, 0.0f, -m_rotZ ); m.apply( viewPoint ); m.setRotationInDegrees( 0.0f, -m_rotY, 0.0f ); m.apply( viewPoint ); m.setRotationInDegrees( -m_rotX, 0.0f, 0.0f ); m.apply( viewPoint ); } else { glDisable( GL_LIGHT0 ); glDisable( GL_LIGHT1 ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity( ); viewPoint[0] = 0.0f; viewPoint[1] = 0.0f; viewPoint[2] = 500000.0f; glTranslatef( -viewPoint[0], -viewPoint[1], -viewPoint[2] ); Matrix m; switch ( m_viewDirection ) { case ViewFront: // do nothing break; case ViewBack: glRotatef( 180.0, 0.0, 1.0, 0.0); m.setRotationInDegrees( 0.0f, -180.0f, 0.0f ); break; case ViewLeft: glRotatef( -90.0, 0.0, 1.0, 0.0); m.setRotationInDegrees( 0.0f, 90.0f, 0.0f ); break; case ViewRight: glRotatef( 90.0, 0.0, 1.0, 0.0); m.setRotationInDegrees( 0.0f, -90.0f, 0.0f ); break; case ViewTop: glRotatef( 90.0, 1.0, 0.0, 0.0); m.setRotationInDegrees( -90.0f, 0.0f, 0.0f ); break; case ViewBottom: glRotatef( -90.0, 1.0, 0.0, 0.0); m.setRotationInDegrees( 90.0f, 0.0f, 0.0f ); break; default: log_error( "Unknown ViewDirection: %d\n", m_viewDirection ); swapBuffers(); return; break; } m.apply( viewPoint ); } if ( !m_capture ) { drawGridLines(); } if ( m_model ) { glColor3f( 0.7, 0.7, 0.7 ); if ( m_viewDirection == ViewPerspective ) { glEnable( GL_LIGHTING ); int opt = Model::DO_TEXTURE | Model::DO_SMOOTHING | ( (g_prefs( "ui_render_bad_textures" ).intValue() == 0) ? 0 : Model::DO_BADTEX); bool drawSelections = (g_prefs( "ui_render_3d_selections" ).intValue() == 0) ? false : true; switch ( m_viewOptions ) { case ViewWireframe: opt = Model::DO_WIREFRAME; drawSelections = true; break; case ViewFlat: opt = Model::DO_NONE; break; case ViewSmooth: opt = Model::DO_SMOOTHING; break; case ViewAlpha: opt = opt | Model::DO_ALPHA; break; default: break; } opt |= ( (g_prefs( "ui_render_backface_cull" ).intValue() == 0) ? 0 : Model::DO_BACKFACECULL); if ( drawSelections ) { glDisable( GL_LIGHTING ); m_model->drawLines(); m_model->drawVertices(); } if ( opt != Model::DO_WIREFRAME ) { glEnable( GL_LIGHTING ); m_model->draw( opt, static_cast( this) , viewPoint ); } if ( drawSelections ) { glDisable( GL_LIGHTING ); glDisable( GL_DEPTH_TEST ); m_model->drawJoints(); } glDisable( GL_LIGHTING ); glDisable( GL_DEPTH_TEST ); m_model->drawPoints(); m_model->drawProjections(); } else { // Draw background drawBackground(); glClear( GL_DEPTH_BUFFER_BIT ); m_model->drawLines(); m_model->drawVertices(); int drawMode = m_model->getCanvasDrawMode(); if ( drawMode != ViewWireframe ) { glEnable( GL_LIGHTING ); glEnable( GL_LIGHT0 ); int opt = Model::DO_TEXTURE | Model::DO_SMOOTHING | ( (g_prefs( "ui_render_bad_textures" ).intValue() == 0) ? 0 : Model::DO_BADTEX); switch ( drawMode ) { case ViewFlat: opt = Model::DO_NONE; break; case ViewSmooth: opt = Model::DO_SMOOTHING; break; case ViewAlpha: opt = opt | Model::DO_ALPHA; break; default: break; } opt |= ( (g_prefs( "ui_render_backface_cull" ).intValue() == 0) ? 0 : Model::DO_BACKFACECULL); m_model->draw( opt, static_cast( this ), viewPoint ); glDisable( GL_LIGHTING ); } glDisable( GL_DEPTH_TEST ); m_model->drawJoints(); m_model->drawPoints(); m_model->drawProjections(); for ( DecalList::iterator it = m_decals.begin(); it != m_decals.end(); it++ ) { (*it)->draw(); } glEnable( GL_DEPTH_TEST ); } } glDisable( GL_LIGHTING ); glDisable( GL_TEXTURE_2D ); if ( !m_capture ) { drawOrigin(); } else { glEnable( GL_DEPTH_TEST ); } if ( this->hasFocus() ) { drawOverlay(); } checkGlErrors(); swapBuffers(); } void ModelViewport::drawGridLines() { if ( m_viewDirection == ViewPerspective || m_viewDirection == ViewOrtho ) { double inc = g_prefs( "ui_3dgrid_inc" ).doubleValue(); double max = g_prefs( "ui_3dgrid_count" ).doubleValue() * inc; double x; double y; double z; glColor3f( 0.55f, 0.55f, 0.55f ); glBegin( GL_LINES ); if ( g_prefs( "ui_3dgrid_xy" ).intValue() != 0 ) { for ( x = -max; x <= max; x += inc ) { glVertex3f( x, -max, 0 ); glVertex3f( x, +max, 0 ); } for ( y = -max; y <= max; y += inc ) { glVertex3f( -max, y, 0 ); glVertex3f( +max, y, 0 ); } } if ( g_prefs( "ui_3dgrid_xz" ).intValue() != 0 ) { for ( x = -max; x <= max; x += inc ) { glVertex3f( x, 0, -max ); glVertex3f( x, 0, +max ); } for ( z = -max; z <= max; z += inc ) { glVertex3f( -max, 0, z ); glVertex3f( +max, 0, z ); } } if ( g_prefs( "ui_3dgrid_yz" ).intValue() != 0 ) { for ( y = -max; y <= max; y += inc ) { glVertex3f( 0, y, -max ); glVertex3f( 0, y, +max ); } for ( z = -max; z <= max; z += inc ) { glVertex3f( 0, -max, z ); glVertex3f( 0, +max, z ); } } glEnd(); } else { double maxDimension = (m_width > m_height) ? m_width : m_height; double unitWidth = g_prefs( "ui_grid_inc" ).doubleValue(); while ( (maxDimension / unitWidth) > 16 ) { unitWidth *= 2.0; } while ( (maxDimension / unitWidth) < 4 ) { unitWidth /= 2.0; } double xRangeMin = 0; double xRangeMax = 0; double yRangeMin = 0; double yRangeMax = 0; double xStart = 0; double yStart = 0; double x = 0; double y = 0; glColor3f( 0.55f, 0.55f, 0.55f ); glBegin( GL_LINES ); switch ( m_viewDirection ) { case ViewFront: xRangeMin = m_arcballPoint[0] - (m_width / 2.0); xRangeMax = m_arcballPoint[0] + (m_width / 2.0); yRangeMin = m_arcballPoint[1] - (m_height / 2.0); yRangeMax = m_arcballPoint[1] + (m_height / 2.0); xStart = unitWidth * ((int) (xRangeMin / unitWidth)); yStart = unitWidth * ((int) (yRangeMin / unitWidth)); for ( x = xStart; x < xRangeMax; x += unitWidth ) { glVertex3f( x, yRangeMin, 0 ); glVertex3f( x, yRangeMax, 0 ); } for ( y = yStart; y < yRangeMax; y += unitWidth ) { glVertex3f( xRangeMin, y, 0 ); glVertex3f( xRangeMax, y, 0 ); } break; case ViewBack: xRangeMin = -m_arcballPoint[0] - (m_width / 2.0); xRangeMax = -m_arcballPoint[0] + (m_width / 2.0); yRangeMin = m_arcballPoint[1] - (m_height / 2.0); yRangeMax = m_arcballPoint[1] + (m_height / 2.0); xStart = unitWidth * ((int) (xRangeMin / unitWidth)); yStart = unitWidth * ((int) (yRangeMin / unitWidth)); for ( x = xStart; x < xRangeMax; x += unitWidth ) { glVertex3f( x, yRangeMin, 0 ); glVertex3f( x, yRangeMax, 0 ); } for ( y = yStart; y < yRangeMax; y += unitWidth ) { glVertex3f( xRangeMin, y, 0 ); glVertex3f( xRangeMax, y, 0 ); } break; case ViewLeft: xRangeMin = -m_arcballPoint[0] - (m_width / 2.0); xRangeMax = -m_arcballPoint[0] + (m_width / 2.0); yRangeMin = m_arcballPoint[1] - (m_height / 2.0); yRangeMax = m_arcballPoint[1] + (m_height / 2.0); xStart = unitWidth * ((int) (xRangeMin / unitWidth)); yStart = unitWidth * ((int) (yRangeMin / unitWidth)); for ( x = xStart; x < xRangeMax; x += unitWidth ) { glVertex3f( 0, yRangeMin, x ); glVertex3f( 0, yRangeMax, x ); } for ( y = yStart; y < yRangeMax; y += unitWidth ) { glVertex3f( 0, y, xRangeMin ); glVertex3f( 0, y, xRangeMax ); } break; case ViewRight: xRangeMin = m_arcballPoint[0] - (m_width / 2.0); xRangeMax = m_arcballPoint[0] + (m_width / 2.0); yRangeMin = m_arcballPoint[1] - (m_height / 2.0); yRangeMax = m_arcballPoint[1] + (m_height / 2.0); xStart = unitWidth * ((int) (xRangeMin / unitWidth)); yStart = unitWidth * ((int) (yRangeMin / unitWidth)); for ( x = xStart; x < xRangeMax; x += unitWidth ) { glVertex3f( 0, yRangeMin, x ); glVertex3f( 0, yRangeMax, x ); } for ( y = yStart; y < yRangeMax; y += unitWidth ) { glVertex3f( 0, y, xRangeMin ); glVertex3f( 0, y, xRangeMax ); } break; case ViewTop: xRangeMin = m_arcballPoint[0] - (m_width / 2.0); xRangeMax = m_arcballPoint[0] + (m_width / 2.0); yRangeMin = -m_arcballPoint[1] - (m_height / 2.0); yRangeMax = -m_arcballPoint[1] + (m_height / 2.0); xStart = unitWidth * ((int) (xRangeMin / unitWidth)); yStart = unitWidth * ((int) (yRangeMin / unitWidth)); for ( x = xStart; x < xRangeMax; x += unitWidth ) { glVertex3f( x, 0, yRangeMin ); glVertex3f( x, 0, yRangeMax ); } for ( y = yStart; y < yRangeMax; y += unitWidth ) { glVertex3f( xRangeMin, 0, y ); glVertex3f( xRangeMax, 0, y ); } break; case ViewBottom: xRangeMin = m_arcballPoint[0] - (m_width / 2.0); xRangeMax = m_arcballPoint[0] + (m_width / 2.0); yRangeMin = m_arcballPoint[1] - (m_height / 2.0); yRangeMax = m_arcballPoint[1] + (m_height / 2.0); xStart = unitWidth * ((int) (xRangeMin / unitWidth)); yStart = unitWidth * ((int) (yRangeMin / unitWidth)); for ( x = xStart; x < xRangeMax; x += unitWidth ) { glVertex3f( x, 0, yRangeMin ); glVertex3f( x, 0, yRangeMax ); } for ( y = yStart; y < yRangeMax; y += unitWidth ) { glVertex3f( xRangeMin, 0, y ); glVertex3f( xRangeMax, 0, y ); } break; default: log_error( "Unhandled view direction: %d\n", m_viewDirection ); break; } glEnd(); glColor3f( 0.35f, 0.35f, 0.35f ); glRasterPos3f( xRangeMin, yRangeMin, 0.0f ); switch ( m_viewDirection ) { case ViewFront: break; case ViewBack: glRasterPos3f( xRangeMax, yRangeMin, 0.0f ); break; case ViewLeft: glRasterPos3f( 0.0f, yRangeMin, xRangeMax ); break; case ViewRight: glRasterPos3f( 0.0f, yRangeMin, xRangeMin ); break; case ViewTop: glRasterPos3f( xRangeMin, 0.0f, yRangeMax ); break; case ViewBottom: glRasterPos3f( xRangeMin, 0.0f, yRangeMin ); break; default: log_error( "Unhandled view direction: %d\n", m_viewDirection ); break; } g_prefs.setDefault( "ui_render_text", 0 ); if ( g_prefs( "ui_render_text" ).intValue() != 0 ) { // Broken with Qt4 + non-accelerated nVidia card (possibly other configs as // well). That is why it is disabled by default. You can set ui_render_text // to a non-zero value in your mm3drc file to enable text rendering. QString text; text.sprintf( "%g", unitWidth ); renderText( 2, this->height() - 12, text, QFont( "Sans", 10 ) ); } } } void ModelViewport::drawOrigin() { glDisable( GL_DEPTH_TEST ); glBegin( GL_LINES ); double scale = m_zoomLevel / 10.0; #ifdef NEWVIEWPORT if ( m_viewDirection == ViewPerspective ) { double x = m_arcballPoint[0]; double y = m_arcballPoint[1]; double z = m_arcballPoint[2] + m_zoomLevel; scale = sqrt( x*x + y*y + z*z ) / 10.0; } #endif // NEWVIEWPORT glColor3f( 1, 0, 0 ); glVertex3f( 0, 0, 0 ); glVertex3f( scale, 0, 0 ); glColor3f( 0, 1, 0 ); glVertex3f( 0, 0, 0 ); glVertex3f( 0, scale, 0 ); glColor3f( 0, 0, 1 ); glVertex3f( 0, 0, 0 ); glVertex3f( 0, 0, scale ); glEnd(); glEnable( GL_DEPTH_TEST ); } void ModelViewport::drawBackground() { glDisable( GL_LIGHTING ); glColor3f( 1.0f, 1.0f, 1.0f ); updateBackground(); if ( m_backgroundFile[0] != '\0' ) { if ( m_viewDirection != ViewPerspective && m_viewDirection != ViewOrtho ) { int index = (int) m_viewDirection - 1; float cenX = 0.0f; float cenY = 0.0f; float cenZ = 0.0f; float minX = 0.0f; float minY = 0.0f; float minZ = 0.0f; float maxX = 0.0f; float maxY = 0.0f; float maxZ = 0.0f; float normX = 0.0f; float normY = 0.0f; float normZ = 0.0f; float w = m_texture->m_origWidth; float h = m_texture->m_origHeight; float dimMax = w > h ? w : h; float scale = m_model->getBackgroundScale( index ); m_model->getBackgroundCenter( index, cenX, cenY, cenZ ); glBindTexture( GL_TEXTURE_2D, m_backgroundTexture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); glEnable( GL_TEXTURE_2D ); glBegin( GL_QUADS ); switch ( m_viewDirection ) { case ViewFront: minZ = maxZ = -((m_farOrtho / 2.0f) - 0.1); minX = -scale * (w / dimMax) + cenX; maxX = scale * (w / dimMax) + cenX; minY = -scale * (h / dimMax) + cenY; maxY = scale * (h / dimMax) + cenY; normZ = 1.0f; break; case ViewBack: minZ = maxZ = ((m_farOrtho / 2.0f) - 0.1); minX = scale * (w / dimMax) + cenX; maxX = -scale * (w / dimMax) + cenX; minY = -scale * (h / dimMax) + cenY; maxY = scale * (h / dimMax) + cenY; normZ = -1.0f; break; case ViewRight: minX = maxX = ((m_farOrtho / 2.0f) - 0.1); minZ = -scale * (w / dimMax) + cenZ; maxZ = scale * (w / dimMax) + cenZ; minY = -scale * (h / dimMax) + cenY; maxY = scale * (h / dimMax) + cenY; normX = 1.0f; break; case ViewLeft: minX = maxX = -((m_farOrtho / 2.0f) - 0.1); minZ = scale * (w / dimMax) + cenZ; maxZ = -scale * (w / dimMax) + cenZ; minY = -scale * (h / dimMax) + cenY; maxY = scale * (h / dimMax) + cenY; normX = -1.0f; break; case ViewTop: minY = maxY = -((m_farOrtho / 2.0f) - 0.1); minX = -scale * (w / dimMax) + cenX; maxX = scale * (w / dimMax) + cenX; minZ = scale * (h / dimMax) + cenZ; maxZ = -scale * (h / dimMax) + cenZ; normY = 1.0f; break; case ViewBottom: minY = maxY = ((m_farOrtho / 2.0f) - 0.1); minX = -scale * (w / dimMax) + cenX; maxX = scale * (w / dimMax) + cenX; minZ = -scale * (h / dimMax) + cenZ; maxZ = scale * (h / dimMax) + cenZ; normY = -1.0f; break; default: break; } if ( m_viewDirection == ViewLeft || m_viewDirection == ViewRight ) { glNormal3f( normX, normY, normZ ); glTexCoord2f( 0.0f, 0.0f ); glVertex3f( minX, minY, minZ ); glNormal3f( normX, normY, normZ ); glTexCoord2f( 0.0f, 1.0f ); glVertex3f( maxX, maxY, minZ ); glNormal3f( normX, normY, normZ ); glTexCoord2f( 1.0f, 1.0f ); glVertex3f( maxX, maxY, maxZ ); glNormal3f( normX, normY, normZ ); glTexCoord2f( 1.0f, 0.0f ); glVertex3f( minX, minY, maxZ ); } else { glNormal3f( normX, normY, normZ ); glTexCoord2f( 0.0f, 0.0f ); glVertex3f( minX, minY, minZ ); glNormal3f( normX, normY, normZ ); glTexCoord2f( 1.0f, 0.0f ); glVertex3f( maxX, minY, minZ ); glNormal3f( normX, normY, normZ ); glTexCoord2f( 1.0f, 1.0f ); glVertex3f( maxX, maxY, maxZ ); glNormal3f( normX, normY, normZ ); glTexCoord2f( 0.0f, 1.0f ); glVertex3f( minX, maxY, maxZ ); } glEnd(); } } } void ModelViewport::drawOverlay() { setViewportOverlay(); glDisable( GL_LIGHTING ); glColor3f( 1.0f, 1.0f, 1.0f ); glEnable( GL_TEXTURE_2D ); int w = this->width(); int h = this->height(); /* glVertex3f( w - , h, 0 ); glVertex3f( w - SCROLL_SIZE, h, 0 ); glVertex3f( w - SCROLL_SIZE, h - SCROLL_SIZE, 0 ); glVertex3f( w, h - SCROLL_SIZE, 0 ); glVertex3f( w - SCROLL_ALL_X, h - SCROLL_ALL_Y, 0 ); glVertex3f( w - SCROLL_ALL_X + SCROLL_SIZE, h - SCROLL_ALL_Y, 0 ); glVertex3f( w - SCROLL_ALL_X + SCROLL_SIZE, h - SCROLL_ALL_Y + SCROLL_SIZE, 0 ); glVertex3f( w - SCROLL_ALL_X, h - SCROLL_ALL_Y + SCROLL_SIZE, 0 ); */ int sx = 0; int sy = 0; int size = SCROLL_SIZE; for ( int b = 0; b < ScrollButtonMAX; b++ ) { ScrollButtonT * sbt = &s_buttons[b]; sx = sbt->x; sy = sbt->y; glBindTexture( GL_TEXTURE_2D, m_scrollTextures[ sbt->texIndex ] ); glBegin( GL_QUADS ); glTexCoord2f( sbt->s1, sbt->t1 ); glVertex3f( w + sx, h + sy, 0 ); glTexCoord2f( sbt->s2, sbt->t2 ); glVertex3f( w + sx + size, h + sy, 0 ); glTexCoord2f( sbt->s3, sbt->t3 ); glVertex3f( w + sx + size, h + sy + size, 0 ); glTexCoord2f( sbt->s4, sbt->t4 ); glVertex3f( w + sx, h + sy + size, 0 ); glEnd(); } glDisable( GL_TEXTURE_2D ); } void ModelViewport::makeTextureFromImage( const QImage & i, GLuint & t ) { glBindTexture( GL_TEXTURE_2D, t ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); int w = i.width(); int h = i.height(); unsigned pixelCount = w * i.height(); uint8_t * data = new uint8_t[ pixelCount * 3 ]; for ( int y = 0; y < h; y ++ ) { for ( int x = 0; x < w; x++ ) { QRgb p = i.pixel( x, h - y - 1 ); data[ ((y * w + x)*3) + 0 ] = qRed( p ); data[ ((y * w + x)*3) + 1 ] = qGreen( p ); data[ ((y * w + x)*3) + 2 ] = qBlue( p ); } } gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE, data ); delete data; } void ModelViewport::updateBackground() { int index = (int) m_viewDirection - 1; std::string filename = m_model->getBackgroundImage( index ); if ( strcmp( filename.c_str(), m_backgroundFile.c_str() ) != 0 ) { m_backgroundFile = filename; if ( m_backgroundFile[0] != '\0' ) { m_texture = TextureManager::getInstance()->getTexture( m_backgroundFile.c_str() ); if ( !m_texture ) { QString str = tr("Could not load background %1").arg( m_backgroundFile.c_str() ); model_status( m_model, StatusError, STATUSTIME_LONG, "%s", (const char *) str.toUtf8() ); m_texture = TextureManager::getInstance()->getDefaultTexture( m_backgroundFile.c_str() ); } glBindTexture( GL_TEXTURE_2D, m_backgroundTexture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); GLuint format = m_texture->m_format == Texture::FORMAT_RGBA ? GL_RGBA : GL_RGB; gluBuild2DMipmaps( GL_TEXTURE_2D, format, m_texture->m_width, m_texture->m_height, format, GL_UNSIGNED_BYTE, m_texture->m_data ); } } } void ModelViewport::adjustViewport() { setViewportDraw(); updateGL(); } void ModelViewport::setViewportDraw() { makeCurrent(); m_inOverlay = false; glViewport( 0, 0, ( GLint ) m_viewportWidth, ( GLint ) m_viewportHeight ); glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); GLfloat ratio = ( GLfloat ) m_viewportWidth / ( GLfloat ) m_viewportHeight; if ( m_viewDirection == ViewPerspective ) { m_far = m_zoomLevel * 2000.0; m_near = m_zoomLevel * 0.002; gluPerspective( 45.0f, ratio, m_near, m_far ); float x = 0.0; float y = 0.0; if ( m_viewportHeight > m_viewportWidth ) { x = m_zoomLevel; y = x / ratio; } else { y = m_zoomLevel; x = y * ratio; } m_width = x * 2.0; m_height = y * 2.0; } else { float x = 0.0; float y = 0.0; if ( m_viewportHeight > m_viewportWidth ) { x = m_zoomLevel; y = x / ratio; } else { y = m_zoomLevel; x = y * ratio; } #ifdef NEWVIEWPORT glOrtho( m_arcballPoint[0] - x, m_arcballPoint[0] + x, m_arcballPoint[1] - y, m_arcballPoint[1] + y, m_nearOrtho, m_farOrtho ); #else // NEWVIEWPORT glOrtho( m_centerX - x, m_centerX + x, m_centerY - y, m_centerY + y, m_nearOrtho, m_farOrtho ); #endif // NEWVIEWPORT m_width = x * 2.0; m_height = y * 2.0; switch ( m_viewDirection ) { case ViewFront: m_rotX = 0; m_rotY = 0; m_rotZ = 0; break; case ViewBack: m_rotX = 0; m_rotY = 180; m_rotZ = 0; break; case ViewLeft: m_rotX = 0; m_rotY = 90; m_rotZ = 0; break; case ViewRight: m_rotX = 0; m_rotY = -90; m_rotZ = 0; break; case ViewTop: m_rotX = -90; m_rotY = 0; m_rotZ = 0; break; case ViewBottom: m_rotX = 90; m_rotY = 0; m_rotZ = 0; break; default: break; } } m_viewMatrix.loadIdentity(); if ( m_viewDirection == ViewOrtho ) { m_viewMatrix.setRotationInDegrees( m_rotX, m_rotY, m_rotZ ); } else { m_viewMatrix.setRotationInDegrees( -m_rotX, -m_rotY, -m_rotZ ); } #ifdef NEWVIEWPORT m_viewMatrix.setTranslation( -m_arcballPoint[0], -m_arcballPoint[1], -m_arcballPoint[2] ); #else // NEWVIEWPORT m_viewMatrix.setTranslation( -m_centerX, -m_centerY, 0.0 ); #endif // NEWVIEWPORT if ( m_viewDirection == ViewOrtho ) { //m_viewMatrix.setRotationInDegrees( m_arcballPoint[0], m_arcballPoint[1], m_arcballPoint[2] ); } m_invMatrix = m_viewMatrix.getInverse(); glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); } void ModelViewport::setViewportOverlay() { makeCurrent(); m_inOverlay = true; glViewport( 0, 0, ( GLint ) m_viewportWidth, ( GLint ) m_viewportHeight ); glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); glOrtho( 0, this->width(), 0, this->height(), m_nearOrtho, m_farOrtho ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity( ); } void ModelViewport::wheelEvent( QWheelEvent * e ) { if ( e->delta() > 0 ) { if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) { rotateClockwise(); } else { zoomIn(); } } else { if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) { rotateCounterClockwise(); } else { zoomOut(); } } } void ModelViewport::zoomIn() { if ( m_activeButton == Qt::NoButton ) { if ( (m_zoomLevel * VP_ZOOMSCALE) > 0.0001 ) { m_zoomLevel *= (VP_ZOOMSCALE); } QString zoomStr; zoomStr.sprintf( "%f", m_zoomLevel ); emit zoomLevelChanged( zoomStr ); makeCurrent(); adjustViewport(); } } void ModelViewport::zoomOut() { if ( m_activeButton == Qt::NoButton ) { if ( (m_zoomLevel / VP_ZOOMSCALE) < 250000 ) { m_zoomLevel /= VP_ZOOMSCALE; } QString zoomStr; zoomStr.sprintf( "%f", m_zoomLevel ); emit zoomLevelChanged( zoomStr ); makeCurrent(); adjustViewport(); } } void ModelViewport::scrollUp() { m_centerY += m_zoomLevel * 0.10f; m_arcballPoint[1] += m_zoomLevel * 0.10f; makeCurrent(); adjustViewport(); } void ModelViewport::scrollDown() { m_centerY -= m_zoomLevel * 0.10f; m_arcballPoint[1] -= m_zoomLevel * 0.10f; makeCurrent(); adjustViewport(); } void ModelViewport::scrollLeft() { m_centerX -= m_zoomLevel * 0.10f; m_arcballPoint[0] -= m_zoomLevel * 0.10f; makeCurrent(); adjustViewport(); } void ModelViewport::scrollRight() { m_centerX += m_zoomLevel * 0.10f; m_arcballPoint[0] += m_zoomLevel * 0.10f; makeCurrent(); adjustViewport(); } void ModelViewport::rotateUp() { rotateViewport( -15.0 * PIOVER180, 0.0 ); makeCurrent(); adjustViewport(); } void ModelViewport::rotateDown() { rotateViewport( 15.0 * PIOVER180, 0.0 ); makeCurrent(); adjustViewport(); } void ModelViewport::rotateLeft() { rotateViewport( 0.0, -15.0 * PIOVER180 ); makeCurrent(); adjustViewport(); } void ModelViewport::rotateRight() { rotateViewport( 0.0, 15.0 * PIOVER180 ); makeCurrent(); adjustViewport(); } void ModelViewport::rotateClockwise() { rotateViewport( 0.0, 0.0, -15.0 * PIOVER180 ); makeCurrent(); adjustViewport(); } void ModelViewport::rotateCounterClockwise() { rotateViewport( 0.0, 0.0, 15.0 * PIOVER180 ); makeCurrent(); adjustViewport(); } void ModelViewport::mousePressEvent( QMouseEvent * e ) { //printf( "press = %d\n", e->button() ); if ( m_activeButton != Qt::NoButton ) { e->ignore(); return; } e->accept(); m_activeButton = e->button(); m_operation = MO_None; int w = this->width(); int h = this->height(); int bx = e->pos().x(); int by = h - e->pos().y(); m_overlayButton = ScrollButtonMAX; int sx = 0; int sy = 0; int size = SCROLL_SIZE; for ( int b = 0; m_overlayButton == ScrollButtonMAX && b < ScrollButtonMAX; b++ ) { sx = s_buttons[b].x; sy = s_buttons[b].y; if ( (bx >= w + sx) && (bx <= w + sx + size) && (by >= h + sy) && (by <= h + sy + size) ) { m_overlayButton = (ScrollButtonE) b; if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) { m_operation = ( m_overlayButton == ScrollButtonPan ) ? MO_Rotate : MO_RotateButton; } else { m_operation = ( m_overlayButton == ScrollButtonPan ) ? MO_Pan : MO_PanButton; } switch ( m_overlayButton ) { case ScrollButtonPan: m_scrollStartPosition = e->pos(); break; case ScrollButtonUp: if ( m_operation == MO_RotateButton ) rotateUp(); else scrollUp(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; case ScrollButtonDown: if ( m_operation == MO_RotateButton ) rotateDown(); else scrollDown(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; case ScrollButtonLeft: if ( m_operation == MO_RotateButton ) rotateLeft(); else scrollLeft(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; case ScrollButtonRight: if ( m_operation == MO_RotateButton ) rotateRight(); else scrollRight(); m_scrollTimer->setSingleShot( true ); m_scrollTimer->start( 300 ); break; default: break; } } } if ( m_operation == MO_None ) { if ( e->button() == Qt::MidButton ) { m_operation = MO_Pan; m_scrollStartPosition = e->pos(); } else if ( (m_viewDirection == ViewPerspective && e->button() == Qt::LeftButton) || (e->modifiers() & Qt::ControlModifier) ) { m_operation = MO_Rotate; m_scrollStartPosition = e->pos(); } else if ( m_viewDirection != ViewPerspective ) { m_operation = MO_Tool; int button = constructButtonState( e ); ::Tool * tool = m_toolbox->getCurrentTool(); tool->mouseButtonDown( this, button, e->pos().x(), e->pos().y() ); } } /* if ( m_overlayButton == ScrollButtonMAX ) { if ( e->button() == Qt::MidButton || (m_viewDirection == ViewPerspective && e->button() == Qt::LeftButton) ) { m_scrollStartPosition = e->pos(); } else { int button = constructButtonState( e ); ::Tool * tool = m_toolbox->getCurrentTool(); tool->mouseButtonDown( this, button, e->pos().x(), e->pos().y() ); } } */ } void ModelViewport::mouseReleaseEvent( QMouseEvent * e ) { //printf( "release = %d\n", e->button() ); if ( e->button() == m_activeButton ) { if ( m_overlayButton == ScrollButtonMAX ) { e->accept(); if ( m_operation == MO_Tool ) { int button = constructButtonState( e ); ::Tool * tool = m_toolbox->getCurrentTool(); tool->mouseButtonUp( this, button, e->pos().x(), e->pos().y() ); m_model->operationComplete( tool->getName( 0 ) ); if ( m_model->getSelectedProjectionCount() > 0 ) { m_model->setDrawProjections( true ); updateView(); } if ( m_model->getSelectedBoneJointCount() > 0 ) { Model::DrawJointModeE mode = static_cast( g_prefs( "ui_draw_joints" ).intValue() ); if ( mode == Model::JOINTMODE_NONE ) mode = Model::JOINTMODE_BONES; m_model->setDrawJoints( mode ); updateView(); } } } else { m_overlayButton = ScrollButtonMAX; m_scrollTimer->stop(); model_status( m_model, StatusNormal, STATUSTIME_SHORT, tr("Use the middle mouse button to drag/pan the viewport").toUtf8() ); } m_activeButton = Qt::NoButton; m_operation = MO_None; } } void ModelViewport::mouseMoveEvent( QMouseEvent * e ) { e->accept(); if ( ! this->hasFocus() ) { this->setFocus(); } if ( m_viewDirection != ViewPerspective ) { int x = e->pos().x(); int y = e->pos().y(); /* double xcoord = 0.0; double ycoord = 0.0; double zcoord = 0.0; getXValue( x, y, &xcoord ); getYValue( x, y, &ycoord ); getZValue( x, y, &zcoord ); */ Vector pos; getParentXYValue( x, y, pos[0], pos[1], true ); m_invMatrix.apply( pos ); for ( int i = 0; i < 3; i++ ) { if ( fabs(pos[i]) < 0.000001 ) pos[i] = 0.0; } char str[80]; PORT_snprintf( str, sizeof(str), "%g, %g, %g", pos[0], pos[1], pos[2] ); model_status( m_model, StatusNormal, STATUSTIME_NONE, str ); } else { model_status( m_model, StatusNormal, STATUSTIME_NONE, "" ); } if ( m_operation == MO_Rotate ) { QPoint curPos = e->pos(); double xDiff = -(m_scrollStartPosition.x() - curPos.x()); double yDiff = -(m_scrollStartPosition.y() - curPos.y()); double rotY = (double) xDiff / (double) this->width() * 3.14159 * 2.0; double rotX = (double) yDiff / (double) this->height() * 3.14159 * 2.0; rotateViewport( rotX, rotY ); m_scrollStartPosition = curPos; } else if ( m_operation == MO_Pan ) { #ifdef NEWVIEWPORT //printf( "adjusting translation\n" ); QPoint curPos = e->pos(); double xDiff = m_scrollStartPosition.x() - curPos.x(); xDiff = xDiff * (m_width / m_viewportWidth); m_centerX += xDiff; double yDiff = m_scrollStartPosition.y() - curPos.y(); yDiff = -yDiff; // Adjust for difference between pixel and GL coordinates yDiff = yDiff * (m_height / m_viewportHeight); m_centerY += yDiff; //m_viewMatrix.inverseRotateVector( vec ); m_arcballPoint[0] += xDiff; m_arcballPoint[1] += yDiff; /* double vec[3]; vec[0] = xDiff; vec[1] = yDiff; vec[2] = 0.0; vec[0] = m_arcballPoint[0]; vec[1] = m_arcballPoint[1]; vec[2] = m_arcballPoint[2]; m_viewMatrix.inverseRotateVector( vec ); log_debug( "World coords = %f,%f,%f\n", vec[0], vec[1], vec[2] ); */ m_scrollStartPosition = curPos; #else //printf( "adjusting translation\n" ); QPoint curPos = e->pos(); double xDiff = m_scrollStartPosition.x() - curPos.x(); m_centerX += xDiff * (m_width / m_viewportWidth); double yDiff = m_scrollStartPosition.y() - curPos.y(); yDiff = -yDiff; // Adjust for difference between pixel and GL coordinates m_centerY += yDiff * (m_height / m_viewportHeight); m_scrollStartPosition = curPos; #endif // NEWVIEWPORT makeCurrent(); adjustViewport(); } else if ( m_operation == MO_Tool ) { //printf( "tool mouse event\n" ); int button = constructButtonState( e ); ::Tool * tool = m_toolbox->getCurrentTool(); tool->mouseButtonMove( this, button, e->pos().x(), e->pos().y() ); } #if 0 if ( m_overlayButton == ScrollButtonMAX ) { if ( m_activeButton ) { if ( m_activeButton == Qt::MidButton || (m_viewDirection == ViewPerspective && m_activeButton == Qt::LeftButton) ) { if ( m_viewDirection == ViewPerspective && (m_activeButton == Qt::LeftButton) ) { QPoint curPos = e->pos(); double xDiff = -(m_scrollStartPosition.x() - curPos.x()); double yDiff = -(m_scrollStartPosition.y() - curPos.y()); Matrix mcur; Matrix mcurinv; double rot[3]; rot[0] = m_rotX * PIOVER180; rot[1] = m_rotY * PIOVER180; rot[2] = m_rotZ * PIOVER180; mcur.setRotation( rot ); mcurinv = mcur.getInverse(); #ifdef NEWVIEWPORT mcur.inverseRotateVector( m_arcballPoint ); #endif // NEWVIEWPORT Vector yvec; yvec.set( 0, 0.0 ); yvec.set( 1, 1.0 ); yvec.set( 2, 0.0 ); yvec.set( 3, 0.0 ); Vector xvec; xvec.set( 0, 1.0 ); xvec.set( 1, 0.0 ); xvec.set( 2, 0.0 ); xvec.set( 3, 0.0 ); Matrix mx; Matrix my; double rotY = (double) xDiff / (double) this->width() * 3.14159 * 2.0; double rotX = (double) yDiff / (double) this->height() * 3.14159 * 2.0; yvec = yvec * mcurinv; my.setRotationOnAxis( yvec.getVector(), rotY ); xvec = xvec * mcurinv; mx.setRotationOnAxis( xvec.getVector(), rotX ); mcur = mx * mcur; mcur = my * mcur; mcur.getRotation( rot ); m_rotX = rot[0] / PIOVER180; m_rotY = rot[1] / PIOVER180; m_rotZ = rot[2] / PIOVER180; //m_rotY += xDiff * PIOVER180 * 14.0; //m_rotX += yDiff * PIOVER180 * 14.0; #ifdef NEWVIEWPORT mcur.apply3( m_arcballPoint ); #endif // NEWVIEWPORT m_scrollStartPosition = curPos; // And finally, update the view makeCurrent(); adjustViewport(); } else { #ifdef NEWVIEWPORT //printf( "adjusting translation\n" ); QPoint curPos = e->pos(); double xDiff = m_scrollStartPosition.x() - curPos.x(); xDiff = xDiff * (m_width / m_viewportWidth); m_centerX += xDiff; double yDiff = m_scrollStartPosition.y() - curPos.y(); yDiff = -yDiff; // Adjust for difference between pixel and GL coordinates yDiff = yDiff * (m_height / m_viewportHeight); m_centerY += yDiff; //m_viewMatrix.inverseRotateVector( vec ); m_arcballPoint[0] += xDiff; m_arcballPoint[1] += yDiff; /* double vec[3]; vec[0] = xDiff; vec[1] = yDiff; vec[2] = 0.0; vec[0] = m_arcballPoint[0]; vec[1] = m_arcballPoint[1]; vec[2] = m_arcballPoint[2]; m_viewMatrix.inverseRotateVector( vec ); log_debug( "World coords = %f,%f,%f\n", vec[0], vec[1], vec[2] ); */ m_scrollStartPosition = curPos; #else //printf( "adjusting translation\n" ); QPoint curPos = e->pos(); double xDiff = m_scrollStartPosition.x() - curPos.x(); m_centerX += xDiff * (m_width / m_viewportWidth); double yDiff = m_scrollStartPosition.y() - curPos.y(); yDiff = -yDiff; // Adjust for difference between pixel and GL coordinates m_centerY += yDiff * (m_height / m_viewportHeight); m_scrollStartPosition = curPos; #endif // NEWVIEWPORT makeCurrent(); adjustViewport(); } } else { //printf( "tool mouse event\n" ); int button = constructButtonState( e ); ::Tool * tool = m_toolbox->getCurrentTool(); tool->mouseButtonMove( this, button, e->pos().x(), e->pos().y() ); } } } else { if ( m_overlayButton == ScrollButtonPan ) { //printf( "adjusting translation\n" ); QPoint curPos = e->pos(); double xDiff = m_scrollStartPosition.x() - curPos.x(); xDiff = xDiff * (m_width / m_viewportWidth); m_centerX += xDiff; double yDiff = m_scrollStartPosition.y() - curPos.y(); yDiff = -yDiff; // Adjust for difference between pixel and GL coordinates yDiff = yDiff * (m_height / m_viewportHeight); m_centerY += yDiff; m_arcballPoint[0] += xDiff; m_arcballPoint[1] += yDiff; m_scrollStartPosition = curPos; makeCurrent(); adjustViewport(); } } #endif // 0 } void ModelViewport::keyPressEvent( QKeyEvent * e ) { if ( m_activeButton == Qt::NoButton ) { switch ( e->key() ) { case Qt::Key_Equal: case Qt::Key_Plus: { if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) { rotateClockwise(); } else { zoomIn(); } } break; case Qt::Key_Minus: case Qt::Key_Underscore: { if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) { rotateCounterClockwise(); } else { zoomOut(); } } break; case Qt::Key_QuoteLeft: { int newDir = 0; switch ( m_viewDirection ) { case ViewPerspective: newDir = ViewOrtho; break; case ViewFront: case ViewBack: case ViewRight: case ViewLeft: case ViewTop: case ViewBottom: case ViewOrtho: newDir = ViewPerspective; break; default: break; } emit viewDirectionChanged( newDir ); } break; case Qt::Key_Backslash: { int newDir = 0; switch ( m_viewDirection ) { case ViewFront: newDir = ViewBack; break; case ViewBack: newDir = ViewFront; break; case ViewRight: newDir = ViewLeft; break; case ViewLeft: newDir = ViewRight; break; case ViewTop: newDir = ViewBottom; break; case ViewBottom: newDir = ViewTop; break; case ViewPerspective: newDir = ViewOrtho; break; case ViewOrtho: newDir = ViewPerspective; break; default: break; } emit viewDirectionChanged( newDir ); } break; case Qt::Key_0: m_centerX = 0.0; m_centerY = 0.0; m_arcballPoint[0] = 0.0; m_arcballPoint[1] = 0.0; m_arcballPoint[2] = 0.0; makeCurrent(); adjustViewport(); break; case Qt::Key_Up: if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) rotateUp(); else scrollUp(); break; case Qt::Key_Down: if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) rotateDown(); else scrollDown(); break; case Qt::Key_Left: if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) rotateLeft(); else scrollLeft(); break; case Qt::Key_Right: if ( (e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) rotateRight(); else scrollRight(); break; case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: case Qt::Key_4: case Qt::Key_5: case Qt::Key_6: case Qt::Key_7: case Qt::Key_8: case Qt::Key_9: if ( e->modifiers() & Qt::ControlModifier ) { log_debug( "set viewport %d\n", e->key() - Qt::Key_1 ); int slot = ( (int) e->key() - (int) Qt::Key_1 ); ViewStateT viewState; viewState.direction = m_viewDirection; viewState.zoom = m_zoomLevel; viewState.rotation[0] = m_rotX; viewState.rotation[1] = m_rotY; viewState.rotation[2] = m_rotZ; viewState.translation[0] = m_arcballPoint[0]; viewState.translation[1] = m_arcballPoint[1]; viewState.translation[2] = m_arcballPoint[2]; emit viewportSaveState( slot, viewState ); } else { log_debug( "viewport recall %d\n", e->key() - Qt::Key_1 ); int slot = ( (int) e->key() - (int) Qt::Key_1 ); emit viewportRecallState( slot ); return; } break; default: QGLWidget::keyPressEvent( e ); return; break; } } e->accept(); } void ModelViewport::rotateViewport( double rotX, double rotY, double rotZ ) { if ( fabs( rotX ) >0.00001 || fabs( rotY ) > 0.00001 || fabs( rotZ ) > 0.00001 ) { if ( m_viewDirection != ViewPerspective && m_viewDirection != ViewOrtho ) { emit viewDirectionChanged( ViewOrtho ); } Matrix mcur; Matrix mcurinv; double rot[3]; rot[0] = m_rotX * PIOVER180; rot[1] = m_rotY * PIOVER180; rot[2] = m_rotZ * PIOVER180; mcur.setRotation( rot ); mcurinv = mcur.getInverse(); #ifdef NEWVIEWPORT mcur.inverseRotateVector( m_arcballPoint ); #endif // NEWVIEWPORT Vector yvec; yvec.set( 0, 0.0 ); yvec.set( 1, 1.0 ); yvec.set( 2, 0.0 ); yvec.set( 3, 0.0 ); Vector xvec; xvec.set( 0, 1.0 ); xvec.set( 1, 0.0 ); xvec.set( 2, 0.0 ); xvec.set( 3, 0.0 ); Vector zvec; zvec.set( 0, 0.0 ); zvec.set( 1, 0.0 ); zvec.set( 2, 1.0 ); zvec.set( 3, 0.0 ); Matrix mx; Matrix my; Matrix mz; zvec = zvec * mcurinv; mz.setRotationOnAxis( zvec.getVector(), rotZ ); yvec = yvec * mcurinv; my.setRotationOnAxis( yvec.getVector(), rotY ); xvec = xvec * mcurinv; mx.setRotationOnAxis( xvec.getVector(), rotX ); mcur = mx * mcur; mcur = my * mcur; mcur = mz * mcur; mcur.getRotation( rot ); m_rotX = rot[0] / PIOVER180; m_rotY = rot[1] / PIOVER180; m_rotZ = rot[2] / PIOVER180; //m_rotY += xDiff * PIOVER180 * 14.0; //m_rotX += yDiff * PIOVER180 * 14.0; #ifdef NEWVIEWPORT mcur.apply3( m_arcballPoint ); #endif // NEWVIEWPORT // And finally, update the view makeCurrent(); adjustViewport(); } } void ModelViewport::setViewState( const ViewStateT & viewState ) { m_viewDirection = viewState.direction; m_zoomLevel = viewState.zoom; m_rotX = viewState.rotation[0]; m_rotY = viewState.rotation[1]; m_rotZ = viewState.rotation[2]; m_arcballPoint[0] = viewState.translation[0]; m_arcballPoint[1] = viewState.translation[1]; m_arcballPoint[2] = viewState.translation[2]; makeCurrent(); adjustViewport(); } void ModelViewport::viewChangeEvent( int dir ) { log_debug( "viewChangeEvent( %d )\n", dir ); if ( dir == m_viewDirection ) { return; } if ( m_viewDirection == ViewPerspective ) //|| m_viewDirection == ViewOrtho ) { Matrix m; m.setRotationInDegrees( 0.0f, 0.0f, -m_rotZ ); m.apply3( m_arcballPoint ); m.setRotationInDegrees( 0.0f, -m_rotY, 0.0f ); m.apply3( m_arcballPoint ); m.setRotationInDegrees( -m_rotX, 0.0f, 0.0f ); m.apply3( m_arcballPoint ); } else { m_invMatrix.apply3( m_arcballPoint ); } log_debug( "center point = %f,%f,%f\n", m_arcballPoint[0], m_arcballPoint[1], m_arcballPoint[2] ); bool toFree = false; switch ( m_viewDirection ) { case ViewFront: case ViewBack: case ViewRight: case ViewLeft: case ViewTop: case ViewBottom: if ( dir == ViewPerspective || dir == ViewOrtho ) { toFree = true; } break; default: break; } if ( toFree ) { log_debug( "inverting rotation\n" ); m_rotX = -m_rotX; m_rotY = -m_rotY; m_rotZ = -m_rotZ; } else { switch ( dir ) { case ViewFront: m_rotX = 0; m_rotY = 0; m_rotZ = 0; break; case ViewBack: m_rotX = 0; m_rotY = 180; m_rotZ = 0; break; case ViewLeft: m_rotX = 0; m_rotY = 90; m_rotZ = 0; break; case ViewRight: m_rotX = 0; m_rotY = -90; m_rotZ = 0; break; case ViewTop: m_rotX = -90; m_rotY = 0; m_rotZ = 0; break; case ViewBottom: m_rotX = 90; m_rotY = 0; m_rotZ = 0; break; default: break; } } Matrix m; m.loadIdentity(); if ( false || (m_viewDirection == ViewPerspective && dir == ViewOrtho) || (m_viewDirection == ViewOrtho && dir == ViewPerspective) ) { m.setRotationInDegrees( m_rotX, m_rotY, m_rotZ ); } else { m.setRotationInDegrees( -m_rotX, -m_rotY, -m_rotZ ); } if ( toFree ) { m = m.getInverse(); } m.apply3( m_arcballPoint ); log_debug( "after point = %f,%f,%f\n", m_arcballPoint[0], m_arcballPoint[1], m_arcballPoint[2] ); m_viewDirection = static_cast( dir ); makeCurrent(); adjustViewport(); } void ModelViewport::setZoomLevel( double zoom ) { if ( m_activeButton == Qt::NoButton ) { m_zoomLevel = zoom; makeCurrent(); adjustViewport(); QString zoomStr; zoomStr.sprintf( "%f", m_zoomLevel ); emit zoomLevelChanged( zoomStr ); } } void ModelViewport::wireframeEvent() { m_viewOptions = ViewWireframe; updateGL(); } void ModelViewport::flatEvent() { m_viewOptions = ViewFlat; updateGL(); } void ModelViewport::smoothEvent() { m_viewOptions = ViewSmooth; updateGL(); } void ModelViewport::textureEvent() { m_viewOptions = ViewTexture; updateGL(); } void ModelViewport::alphaEvent() { m_viewOptions = ViewAlpha; updateGL(); } void ModelViewport::scrollTimeout() { if ( m_operation == MO_RotateButton ) { switch ( m_overlayButton ) { case ScrollButtonUp: rotateUp(); break; case ScrollButtonDown: rotateDown(); break; case ScrollButtonLeft: rotateLeft(); break; case ScrollButtonRight: rotateRight(); break; default: m_scrollTimer->stop(); return; } } else { switch ( m_overlayButton ) { case ScrollButtonUp: scrollUp(); break; case ScrollButtonDown: scrollDown(); break; case ScrollButtonLeft: scrollLeft(); break; case ScrollButtonRight: scrollRight(); break; default: m_scrollTimer->stop(); return; } } m_scrollTimer->setSingleShot( false ); m_scrollTimer->start( 100 ); } void ModelViewport::focusInEvent( QFocusEvent * e ) { m_backColor.setRgb( 150, 210, 210 ); makeCurrent(); glClearColor( m_backColor.red() / 256.0, m_backColor.green() / 256.0, m_backColor.blue() / 256.0, 1.0f ); updateGL(); } void ModelViewport::focusOutEvent( QFocusEvent * e ) { m_backColor.setRgb( 130, 200, 200 ); makeCurrent(); glClearColor( m_backColor.red() / 256.0, m_backColor.green() / 256.0, m_backColor.blue() / 256.0, 1.0f ); updateGL(); } /* void ModelViewport::dragEnterEvent( QDragMoveEvent * e ) { log_debug( "got drag enter event\n" ); if ( QUriDrag::canDecode( e ) ) { log_debug( "is URI\n" ); } if ( QTextDrag::canDecode( e ) ) { log_debug( "is Text\n" ); } if ( QImageDrag::canDecode( e ) ) { log_debug( "is Image\n" ); } //e->accept( QRect( 0, 0, this->width(), this->height() ) ); } */ void ModelViewport::getParentXYValue( int x, int y, double & xval, double & yval, bool selected ) { xval = (((double) x / (double) m_viewportWidth) * m_width) - (m_width / 2.0); yval = (((double) -y / (double) m_viewportHeight) * m_height) + (m_height / 2.0); double maxDist = (4.1 / (double) m_viewportWidth) * m_width; if ( g_prefs.exists( "ui_snap_vertex" ) && g_prefs( "ui_snap_vertex" ).intValue() != 0 ) { // snap to vertex double curDist = maxDist; int curIndex = -1; Model::PositionTypeE curType = Model::PT_Vertex; const Matrix & mat = getParentViewMatrix(); double coord[3] = { 0, 0, 0 }; double saveCoord[3] = { 0, 0, 0 }; size_t vcount = m_model->getVertexCount(); for ( size_t v = 0; v < vcount; v++ ) { if ( selected || !m_model->isVertexSelected( v ) ) { m_model->getVertexCoords( v, coord ); mat.apply3( coord ); coord[0] += mat.get(3,0); coord[1] += mat.get(3,1); coord[2] += mat.get(3,2); double xdiff = coord[0] - xval; double ydiff = coord[1] - yval; double diff = sqrt( xdiff*xdiff + ydiff*ydiff ); if ( diff < curDist ) { curDist = diff; curIndex = v; curType = Model::PT_Vertex; saveCoord[0] = coord[0]; saveCoord[1] = coord[1]; saveCoord[2] = coord[2]; } } } size_t bcount = m_model->getBoneJointCount(); for ( size_t b = 0; b < bcount; b++ ) { if ( selected || !m_model->isBoneJointSelected( b ) ) { m_model->getBoneJointCoords( b, coord ); mat.apply3( coord ); coord[0] += mat.get(3,0); coord[1] += mat.get(3,1); coord[2] += mat.get(3,2); double xdiff = coord[0] - xval; double ydiff = coord[1] - yval; double diff = sqrt( xdiff*xdiff + ydiff*ydiff ); if ( diff < curDist ) { curDist = diff; curIndex = b; curType = Model::PT_Joint; saveCoord[0] = coord[0]; saveCoord[1] = coord[1]; saveCoord[2] = coord[2]; } } } size_t p; size_t pcount = m_model->getPointCount(); for ( p = 0; p < pcount; p++ ) { if ( selected || !m_model->isPointSelected( p ) ) { m_model->getPointCoords( p, coord ); mat.apply3( coord ); coord[0] += mat.get(3,0); coord[1] += mat.get(3,1); coord[2] += mat.get(3,2); double xdiff = coord[0] - xval; double ydiff = coord[1] - yval; double diff = sqrt( xdiff*xdiff + ydiff*ydiff ); if ( diff < curDist ) { curDist = diff; curIndex = p; curType = Model::PT_Point; saveCoord[0] = coord[0]; saveCoord[1] = coord[1]; saveCoord[2] = coord[2]; } } } pcount = m_model->getProjectionCount(); for ( p = 0; p < pcount; p++ ) { if ( selected || !m_model->isProjectionSelected( p ) ) { m_model->getProjectionCoords( p, coord ); mat.apply3( coord ); coord[0] += mat.get(3,0); coord[1] += mat.get(3,1); coord[2] += mat.get(3,2); double xdiff = coord[0] - xval; double ydiff = coord[1] - yval; double diff = sqrt( xdiff*xdiff + ydiff*ydiff ); if ( diff < curDist ) { curDist = diff; curIndex = p; curType = Model::PT_Projection; saveCoord[0] = coord[0]; saveCoord[1] = coord[1]; saveCoord[2] = coord[2]; } } } if ( curIndex >= 0 ) { xval = saveCoord[0]; yval = saveCoord[1]; maxDist = 0.0; } } if ( m_viewDirection != ViewOrtho && g_prefs.exists( "ui_snap_grid" ) && g_prefs( "ui_snap_grid" ).intValue() != 0 ) { // snap to grid double unitWidth = 1.0; double maxDimension = (m_width > m_height) ? m_width : m_height; unitWidth = g_prefs( "ui_grid_inc" ).doubleValue(); while ( (maxDimension / unitWidth) > 16 ) { unitWidth *= 2.0; } while ( (maxDimension / unitWidth) < 4 ) { unitWidth /= 2.0; } double val; int mult; double fudge; fudge = 0.5; #ifdef NEWVIEWPORT double x = xval + m_arcballPoint[0]; #else // NEWVIEWPORT double x = xval + m_centerX; #endif // NEWVIEWPORT if ( x < 0.0 ) { fudge = -0.5; } mult = (int) (x / unitWidth + fudge); val = (double) mult * unitWidth; if ( fabs( x - val ) < maxDist ) { #ifdef NEWVIEWPORT xval = val - m_arcballPoint[0]; #else // NEWVIEWPORT xval = val - m_centerX; #endif // NEWVIEWPORT } fudge = 0.5; #ifdef NEWVIEWPORT double y = yval + m_arcballPoint[1]; #else // NEWVIEWPORT double y = yval + m_centerY; #endif // NEWVIEWPORT if ( y < 0.0 ) { fudge = -0.5; } mult = (int) (y / unitWidth + fudge); val = (double) mult * unitWidth; if ( fabs( y - val ) < maxDist ) { #ifdef NEWVIEWPORT yval = val - m_arcballPoint[1]; #else // NEWVIEWPORT yval = val - m_centerY; #endif // NEWVIEWPORT } } } void ModelViewport::getRawParentXYValue( int x, int y, double & xval, double & yval ) { xval = (((double) x / (double) m_viewportWidth) * m_width) - (m_width / 2.0); yval = (((double) -y / (double) m_viewportHeight) * m_height) + (m_height / 2.0); } #ifdef NEWVIEWPORT bool ModelViewport::getXValue( int x, int y, double * val ) { Vector vec; vec[0] = (((double) x / (double) m_viewportWidth) * m_width) - (m_width / 2.0); vec[1] = -((((double) y / (double) m_viewportHeight) * m_height) - (m_height / 2.0)); vec[2] = 0.0; m_invMatrix.apply( vec ); *val = vec[0]; switch ( m_viewDirection ) { case ViewFront: case ViewTop: case ViewBottom: case ViewBack: case ViewOrtho: return true; default: break; } return false; } bool ModelViewport::getYValue( int x, int y, double * val ) { Vector vec; vec[0] = (((double) x / (double) m_viewportWidth) * m_width) - (m_width / 2.0); vec[1] = -((((double) y / (double) m_viewportHeight) * m_height) - (m_height / 2.0)); vec[2] = 0.0; m_invMatrix.apply( vec ); *val = vec[1]; switch ( m_viewDirection ) { case ViewFront: case ViewBack: case ViewLeft: case ViewRight: case ViewOrtho: return true; default: break; } return false; } bool ModelViewport::getZValue( int x, int y, double * val ) { Vector vec; vec[0] = (((double) x / (double) m_viewportWidth) * m_width) - (m_width / 2.0); vec[1] = -((((double) y / (double) m_viewportHeight) * m_height) - (m_height / 2.0)); vec[2] = 0.0; m_invMatrix.apply( vec ); *val = vec[2]; switch ( m_viewDirection ) { case ViewLeft: case ViewRight: case ViewTop: case ViewBottom: case ViewOrtho: return true; default: break; } return false; } #else // NEWVIEWPORT bool ModelViewport::getXValue( int x, int y, double * val ) { switch ( m_viewDirection ) { case ViewFront: case ViewTop: case ViewBottom: *val = (m_centerX - (m_width / 2.0)) + (((double) x / (double) m_viewportWidth) * m_width); break; case ViewBack: *val = ((-m_centerX) + (m_width / 2.0)) + (((double) (-x) / (double) m_viewportWidth) * m_width); break; case ViewRight: case ViewLeft: default: return false; } return true; } bool ModelViewport::getYValue( int x, int y, double * val ) { switch ( m_viewDirection ) { case ViewFront: case ViewBack: case ViewRight: case ViewLeft: *val = (m_centerY + (m_height / 2.0)) - (((double) y / (double) m_viewportHeight) * m_height); break; case ViewTop: case ViewBottom: default: return false; break; } return true; } bool ModelViewport::getZValue( int x, int y, double * val ) { switch ( m_viewDirection ) { case ViewTop: *val = ((-m_centerY) - (m_height / 2.0)) - (((double) (-y) / (double) m_viewportHeight) * m_height); break; case ViewBottom: *val = (m_centerY + (m_height / 2.0)) - (((double) y / (double) m_viewportHeight) * m_height); //*val = (m_centerY + (m_height / 2.0)) - (((double) y / (double) m_viewportHeight) * m_height); break; case ViewRight: *val = (m_centerX - (m_width / 2.0)) + (((double) x / (double) m_viewportWidth) * m_width); break; case ViewLeft: *val = ((-m_centerX) + (m_width / 2.0)) + (((double) (-x) / (double) m_viewportWidth) * m_width); break; case ViewFront: case ViewBack: default: return false; } return true; } #endif // NEWVIEWPORT int ModelViewport::constructButtonState( QMouseEvent * e ) { int button = 0; //switch ( e->button() ) switch ( m_activeButton ) { case Qt::LeftButton: button = ::Tool::BS_Left; break; case Qt::MidButton: button = ::Tool::BS_Middle; break; case Qt::RightButton: button = ::Tool::BS_Right; break; default: break; } if ( e->modifiers() & Qt::ShiftModifier ) { button |= ::Tool::BS_Shift; } if ( e->modifiers() & Qt::AltModifier ) { button |= ::Tool::BS_Alt; } if ( e->modifiers() & Qt::ControlModifier ) { button |= ::Tool::BS_Ctrl; } return button; } void ModelViewport::updateView() { updateGL(); StatusObject * bar = model_status_get_object( m_model ); bar->setVertices( m_model->getVertexCount(), m_model->getSelectedVertexCount() ); bar->setFaces( m_model->getTriangleCount(), m_model->getSelectedTriangleCount() ); bar->setGroups( m_model->getGroupCount() ); bar->setBoneJoints( m_model->getBoneJointCount(), m_model->getSelectedBoneJointCount() ); bar->setPoints( m_model->getPointCount(), m_model->getSelectedPointCount() ); bar->setTextures( m_model->getTextureCount() ); } void ModelViewport::update3dView() { if ( m_viewDirection == ViewPerspective ) { updateView(); } } void ModelViewport::addDecal( Decal * decal ) { m_decals.push_back( decal ); updateGL(); } void ModelViewport::removeDecal( Decal * decal ) { m_decals.remove( decal ); updateGL(); } void ModelViewport::frameArea( double x1, double y1, double z1, double x2, double y2, double z2 ) { double centerX = (x1 + x2) / 2.0; double centerY = (y1 + y2) / 2.0; double centerZ = (z1 + z2) / 2.0; double width = fabs( x1 - x2 ); double height = fabs( y1 - y2 ); double depth = fabs( z1 - z2 ); if ( width < 0.0001667 ) { width = 0.0001667; } if ( height < 0.0001667 ) { height = 0.0001667; } if ( depth < 0.0001667 ) { depth = 0.0001667; } width *= 1.20; height *= 1.20; depth *= 1.20; Vector bounds; bounds[0] = width; bounds[1] = height; bounds[2] = depth; double viewWidth = 0.0; double viewHeight = 0.0; switch ( m_viewDirection ) { #ifdef NEWVIEWPORT case ViewFront: case ViewBack: case ViewRight: case ViewLeft: case ViewTop: case ViewBottom: case ViewOrtho: case ViewPerspective: { m_arcballPoint[0] = centerX; m_arcballPoint[1] = centerY; m_arcballPoint[2] = centerZ; //log_debug( "view = %d (%f,%f,%f)\n", // (int) m_viewDirection, // m_rotX, m_rotY, m_rotZ ); double rx = m_rotX; double ry = m_rotY; double rz = m_rotZ; if ( m_viewDirection != ViewPerspective || m_viewDirection == ViewOrtho ) { rx = -rx; ry = -ry; rz = -rz; } //m_viewMatrix.apply3( m_arcballPoint ); if ( m_viewDirection == ViewOrtho ) { Matrix m; m_viewMatrix.apply3( m_arcballPoint ); m_viewMatrix.apply3( bounds ); /* m.setRotationInDegrees( rx, 0.0f, 0.0f ); m.apply3( m_arcballPoint ); m.apply3( bounds ); m.setRotationInDegrees( 0.0f, ry, 0.0f ); m.apply3( m_arcballPoint ); m.apply3( bounds ); m.setRotationInDegrees( 0.0f, 0.0f, rz ); m.apply3( m_arcballPoint ); m.apply3( bounds ); */ } else { Matrix m; m.setRotationInDegrees( rx, 0.0f, 0.0f ); m.apply3( m_arcballPoint ); m.apply3( bounds ); m.setRotationInDegrees( 0.0f, ry, 0.0f ); m.apply3( m_arcballPoint ); m.apply3( bounds ); m.setRotationInDegrees( 0.0f, 0.0f, rz ); m.apply3( m_arcballPoint ); m.apply3( bounds ); } if ( m_viewDirection == ViewPerspective || m_viewDirection == ViewOrtho ) { viewWidth = viewHeight = sqrt( height*height + width*width + depth*depth ) * 1.2; } else { viewWidth = fabs( bounds[0] ); viewHeight = fabs( bounds[1] ); } //log_debug( "point = %d (%f,%f,%f)\n", // (int) m_viewDirection, // m_arcballPoint[0], m_arcballPoint[1], m_arcballPoint[2] ); } break; default: return; break; #else // NEWVIEWPORT case ViewFront: m_centerX = centerX; m_centerY = centerY; viewWidth = width; viewHeight = height; break; case ViewBack: m_centerX = -centerX; m_centerY = centerY; viewWidth = width; viewHeight = height; break; case ViewRight: m_centerX = centerZ; m_centerY = centerY; viewWidth = depth; viewHeight = height; break; case ViewLeft: m_centerX = -centerZ; m_centerY = centerY; viewWidth = depth; viewHeight = height; break; case ViewTop: m_centerX = centerX; m_centerY = -centerZ; viewWidth = width; viewHeight = depth; break; case ViewBottom: m_centerX = centerX; m_centerY = centerZ; viewWidth = width; viewHeight = depth; break; case ViewPerspective: { double rotation[3]; rotation[0] = m_rotX * PIOVER180; rotation[1] = m_rotY * PIOVER180; rotation[2] = m_rotZ * PIOVER180; Matrix m; m.setRotation( rotation ); double v[3]; v[0] = centerX; v[1] = centerY; v[2] = centerZ; m.inverseRotateVector( v ); m_centerX = v[0]; m_centerY = v[1]; viewWidth = height; viewHeight = width; } break; default: return; break; #endif // NEWVIEWPORT } if ( viewWidth > viewHeight ) { if ( m_viewDirection == ViewPerspective ) { m_zoomLevel = viewWidth / 2.0; } else { m_zoomLevel = viewWidth / 2.0; } } else { if ( m_viewDirection == ViewPerspective ) { m_zoomLevel = viewHeight / 2.0; } else { m_zoomLevel = viewHeight / 2.0; } } QString zoomStr; zoomStr.sprintf( "%f", m_zoomLevel ); emit zoomLevelChanged( zoomStr ); makeCurrent(); adjustViewport(); } void ModelViewport::checkGlErrors() { int error = glGetError(); if ( error ) { switch ( error ) { case GL_INVALID_VALUE: model_status( m_model, StatusNormal, STATUSTIME_NONE, tr("OpenGL error = Invalid Value").toUtf8() ); break; case GL_INVALID_ENUM: model_status( m_model, StatusNormal, STATUSTIME_NONE, tr("OpenGL error = Invalid Enum").toUtf8() ); break; case GL_INVALID_OPERATION: model_status( m_model, StatusNormal, STATUSTIME_NONE, tr("OpenGL error = Invalid Operation").toUtf8() ); break; case GL_STACK_OVERFLOW: model_status( m_model, StatusNormal, STATUSTIME_NONE, tr("OpenGL error = Stack Overflow").toUtf8() ); break; case GL_STACK_UNDERFLOW: model_status( m_model, StatusNormal, STATUSTIME_NONE, tr("OpenGL error = Stack Underflow").toUtf8() ); break; case GL_OUT_OF_MEMORY: model_status( m_model, StatusNormal, STATUSTIME_NONE, tr("OpenGL error = Out Of Memory").toUtf8() ); break; default: model_status( m_model, StatusNormal, STATUSTIME_NONE, tr("OpenGL error = Unknown").toUtf8() ); break; } } } void ModelViewport::copyContentsToTexture( Texture * tex ) { makeCurrent(); m_capture = true; if ( tex ) { unsigned w = this->width(); unsigned h = this->height(); // make sure texture can hold data if ( tex->m_data ) { unsigned bpp = (tex->m_format == Texture::FORMAT_RGB) ? 3 : 4; if ( (tex->m_width * tex->m_height * bpp) < (w * h * 4) ) { delete[] tex->m_data; tex->m_data = NULL; } } if ( tex->m_data == NULL ) { tex->m_data = new uint8_t[ w * h * 4 ]; } tex->m_width = w; tex->m_height = h; tex->m_format = Texture::FORMAT_RGBA; makeCurrent(); updateGL(); glReadPixels( 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, tex->m_data ); } makeCurrent(); glClearColor( m_backColor.red() / 256.0, m_backColor.green() / 256.0, m_backColor.blue() / 256.0, 1.0f ); m_capture = false; } void ModelViewport::updateCaptureGL() { m_capture = true; makeCurrent(); updateGL(); m_capture = false; } mm3d-1.3.7/src/depui/textureframe.cc0000644000175000017500000000757710746740245014253 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "textureframe.h" #include "texwidget.h" #include "texture.h" #include "model.h" #include "log.h" #include #include #include TextureFrame::TextureFrame( QWidget * parent ) : QFrame( parent ), m_materialId( -1 ), m_texture( NULL ), m_3d( false ), m_overrideSize( false ), m_overWidth( 1 ), m_overHeight( 1 ) { setFrameStyle( StyledPanel ); setFrameShadow( Sunken ); m_textureWidget= new TextureWidget( this ); } TextureFrame::~TextureFrame() { } void TextureFrame::setModel( Model * model ) { m_model = model; if ( m_textureWidget ) { m_textureWidget->setModel( model ); } } void TextureFrame::set3d( bool o ) { m_3d = o; if ( m_textureWidget ) { m_textureWidget->set3d( o ); updateSize(); } } void TextureFrame::resizeEvent( QResizeEvent * e ) { updateSize(); } void TextureFrame::textureChangedEvent( int materialId ) { m_materialId = materialId - 1; m_texture = m_model->getTextureData( m_materialId ); // Okay to pass null here m_textureWidget->setTexture( m_materialId, m_texture ); updateSize(); } void TextureFrame::resizeTexture( int width, int height ) { if ( m_texture || m_overrideSize ) { if ( m_3d ) { m_textureWidget->move( PAD_SIZE, PAD_SIZE ); m_textureWidget->resize( width, height ); } else { float x = 0.0; float y = 0.0; float scaleX = 1.0; float scaleY = 1.0; if ( m_overrideSize ) { x = m_overWidth; y = m_overHeight; } else { if ( m_texture ) { x = m_texture->m_origWidth; y = m_texture->m_origHeight; } else { x = 256.0; y = 256.0; } } scaleX = width / x; scaleY = height / y; if ( scaleX < scaleY ) { m_textureWidget->move( PAD_SIZE, (int) ((this->height() - (y * scaleX)) / 2) + PAD_SIZE ); m_textureWidget->resize( (int) (x * scaleX), (int) (y * scaleX) ); } else { m_textureWidget->move( (int) ((this->width() - (x * scaleY)) / 2) + PAD_SIZE, PAD_SIZE ); m_textureWidget->resize( (int) (x * scaleY), (int) (y * scaleY) ); } } } else { m_textureWidget->move( PAD_SIZE, PAD_SIZE ); m_textureWidget->resize( this->width() - PAD_SIZE * 2, this->height() - PAD_SIZE * 2); } } void TextureFrame::setTexture( int materialId, Texture * tex ) { m_materialId = materialId; m_texture = tex; m_textureWidget->setTexture( m_materialId, tex ); updateSize(); } void TextureFrame::updateSize() { resizeTexture( width() - PAD_SIZE*2, height() - PAD_SIZE*2 ); } void TextureFrame::sizeOverride( int width, int height ) { m_textureWidget->resize( 0, 0 ); m_overrideSize = true; m_overWidth = width; m_overHeight = height; updateSize(); } mm3d-1.3.7/src/depui/modelviewport.moc.cc0000644000175000017500000001366611025504137015176 00000000000000/**************************************************************************** ** Meta object code from reading C++ file 'modelviewport.h' ** ** Created: Mon Jun 16 08:35:59 2008 ** by: The Qt Meta Object Compiler version 59 (Qt 4.2.3) ** ** WARNING! All changes made in this file will be lost! *****************************************************************************/ #include "modelviewport.h" #if !defined(Q_MOC_OUTPUT_REVISION) #error "The header file 'modelviewport.h' doesn't include ." #elif Q_MOC_OUTPUT_REVISION != 59 #error "This file was generated using the moc from 4.2.3. It" #error "cannot be used with the include files from this version of Qt." #error "(The moc has changed too much.)" #endif static const uint qt_meta_data_ModelViewport[] = { // content: 1, // revision 0, // classname 0, 0, // classinfo 21, 10, // methods 0, 0, // properties 0, 0, // enums/sets // signals: signature, parameters, type, tag, flags 23, 15, 14, 14, 0x05, 53, 49, 14, 14, 0x05, 79, 14, 14, 14, 0x05, 115, 94, 14, 14, 0x05, 175, 164, 14, 14, 0x05, // slots: signature, parameters, type, tag, flags 200, 49, 14, 14, 0x0a, 231, 221, 14, 14, 0x0a, 262, 252, 14, 14, 0x0a, 302, 14, 14, 14, 0x0a, 319, 14, 14, 14, 0x0a, 331, 14, 14, 14, 0x0a, 345, 14, 14, 14, 0x0a, 360, 14, 14, 14, 0x0a, 373, 14, 14, 14, 0x0a, 391, 389, 14, 14, 0x09, 416, 389, 14, 14, 0x09, 445, 389, 14, 14, 0x09, 475, 389, 14, 14, 0x09, 507, 389, 14, 14, 0x09, 533, 389, 14, 14, 0x09, 560, 389, 14, 14, 0x09, 0 // eod }; static const char qt_meta_stringdata_ModelViewport[] = { "ModelViewport\0\0zoomStr\0zoomLevelChanged(QString)\0" "dir\0viewDirectionChanged(int)\0" "modelUpdated()\0slotNumber,viewState\0" "viewportSaveState(int,ModelViewport::ViewStateT)\0" "slotNumber\0viewportRecallState(int)\0" "viewChangeEvent(int)\0zoomLevel\0" "setZoomLevel(double)\0viewState\0" "setViewState(ModelViewport::ViewStateT)\0" "wireframeEvent()\0flatEvent()\0smoothEvent()\0" "textureEvent()\0alphaEvent()\0scrollTimeout()\0" "e\0wheelEvent(QWheelEvent*)\0" "mouseMoveEvent(QMouseEvent*)\0" "mousePressEvent(QMouseEvent*)\0" "mouseReleaseEvent(QMouseEvent*)\0" "keyPressEvent(QKeyEvent*)\0" "focusInEvent(QFocusEvent*)\0" "focusOutEvent(QFocusEvent*)\0" }; const QMetaObject ModelViewport::staticMetaObject = { { &QGLWidget::staticMetaObject, qt_meta_stringdata_ModelViewport, qt_meta_data_ModelViewport, 0 } }; const QMetaObject *ModelViewport::metaObject() const { return &staticMetaObject; } void *ModelViewport::qt_metacast(const char *_clname) { if (!_clname) return 0; if (!strcmp(_clname, qt_meta_stringdata_ModelViewport)) return static_cast(const_cast< ModelViewport*>(this)); if (!strcmp(_clname, "Tool::Parent")) return static_cast< Tool::Parent*>(const_cast< ModelViewport*>(this)); return QGLWidget::qt_metacast(_clname); } int ModelViewport::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QGLWidget::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: zoomLevelChanged((*reinterpret_cast< const QString(*)>(_a[1]))); break; case 1: viewDirectionChanged((*reinterpret_cast< int(*)>(_a[1]))); break; case 2: modelUpdated(); break; case 3: viewportSaveState((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< const ModelViewport::ViewStateT(*)>(_a[2]))); break; case 4: viewportRecallState((*reinterpret_cast< int(*)>(_a[1]))); break; case 5: viewChangeEvent((*reinterpret_cast< int(*)>(_a[1]))); break; case 6: setZoomLevel((*reinterpret_cast< double(*)>(_a[1]))); break; case 7: setViewState((*reinterpret_cast< const ModelViewport::ViewStateT(*)>(_a[1]))); break; case 8: wireframeEvent(); break; case 9: flatEvent(); break; case 10: smoothEvent(); break; case 11: textureEvent(); break; case 12: alphaEvent(); break; case 13: scrollTimeout(); break; case 14: wheelEvent((*reinterpret_cast< QWheelEvent*(*)>(_a[1]))); break; case 15: mouseMoveEvent((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break; case 16: mousePressEvent((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break; case 17: mouseReleaseEvent((*reinterpret_cast< QMouseEvent*(*)>(_a[1]))); break; case 18: keyPressEvent((*reinterpret_cast< QKeyEvent*(*)>(_a[1]))); break; case 19: focusInEvent((*reinterpret_cast< QFocusEvent*(*)>(_a[1]))); break; case 20: focusOutEvent((*reinterpret_cast< QFocusEvent*(*)>(_a[1]))); break; } _id -= 21; } return _id; } // SIGNAL 0 void ModelViewport::zoomLevelChanged(const QString & _t1) { void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 0, _a); } // SIGNAL 1 void ModelViewport::viewDirectionChanged(int _t1) { void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 1, _a); } // SIGNAL 2 void ModelViewport::modelUpdated() { QMetaObject::activate(this, &staticMetaObject, 2, 0); } // SIGNAL 3 void ModelViewport::viewportSaveState(int _t1, const ModelViewport::ViewStateT & _t2) { void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)), const_cast(reinterpret_cast(&_t2)) }; QMetaObject::activate(this, &staticMetaObject, 3, _a); } // SIGNAL 4 void ModelViewport::viewportRecallState(int _t1) { void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)) }; QMetaObject::activate(this, &staticMetaObject, 4, _a); } mm3d-1.3.7/src/depui/Makefile.am0000644000175000017500000000112710752502235013236 00000000000000noinst_LIBRARIES = libdepui.a libdepui_HFILES = \ errorobj.h \ modelviewport.h \ textureframe.h \ texwidget.h libdepui_MOC = \ errorobj.moc.cc \ modelviewport.moc.cc \ textureframe.moc.cc \ texwidget.moc.cc libdepui_a_SOURCES = \ errorobj.cc \ modelviewport.cc \ textureframe.cc \ texwidget.cc \ $(libdepui_MOC) \ $(libdepui_HFILES) %.moc.cc: %.h $(QT_MOC) -o $@ $< AM_CPPFLAGS = $(CORE_PROFILE) -coverage -Wall -I../libmm3d -I../mm3dcore -I../ -DMM3D_EDIT $(all_includes) $(QT_CXXFLAGS) $(LUALIB_CCFLAGS) $(GL_CFLAGS) CLEANFILES = $(libdepui_MOC) *.gcno *.gcda mm3d-1.3.7/src/depui/errorobj.cc0000644000175000017500000001025711027551623013342 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "errorobj.h" ErrorObject g_errorObject; ErrorObject::ErrorObject( QObject * parent ) : QObject( parent ) { } ErrorObject::~ErrorObject() { } QString ErrorObject::getModelErrorString( Model::ModelErrorE err, Model * model ) { switch ( err ) { case Model::ERROR_NONE: return tr("Success"); case Model::ERROR_CANCEL: return tr("Canceled"); case Model::ERROR_UNKNOWN_TYPE: return tr("Unrecognized file extension (unknown type)"); case Model::ERROR_UNSUPPORTED_OPERATION: return tr("Operation not supported for this file type"); case Model::ERROR_BAD_ARGUMENT: return tr("Invalid argument (internal error)"); case Model::ERROR_NO_FILE: return tr("File does not exist"); case Model::ERROR_NO_ACCESS: return tr("Permission denied"); case Model::ERROR_FILE_OPEN: return tr("Could not open file"); case Model::ERROR_FILE_READ: return tr("Could not read from file"); case Model::ERROR_BAD_MAGIC: return tr("File is the wrong type or corrupted"); case Model::ERROR_UNSUPPORTED_VERSION: return tr("Unsupported version"); case Model::ERROR_BAD_DATA: return tr("File contains invalid data"); case Model::ERROR_UNEXPECTED_EOF: return tr("Unexpected end of file"); case Model::ERROR_EXPORT_ONLY: return tr("Write not supported, try \"Export...\""); case Model::ERROR_FILTER_SPECIFIC: if ( model ) { return QString::fromUtf8( model->getFilterSpecificError() ); } else { return QString::fromUtf8( Model::getLastFilterSpecificError() ); } case Model::ERROR_UNKNOWN: return tr("Unknown error"); default: break; } return QString("FIXME: Untranslated model error"); } QString ErrorObject::getTextureErrorString( Texture::ErrorE err ) { switch ( err ) { case Texture::ERROR_NONE: return tr("Success"); case Texture::ERROR_NO_FILE: return tr("File does not exist"); case Texture::ERROR_NO_ACCESS: return tr("Permission denied"); case Texture::ERROR_FILE_OPEN: return tr("Could not open file"); case Texture::ERROR_FILE_READ: return tr("Could not read from file"); case Texture::ERROR_FILE_WRITE: return tr("Could not write file"); case Texture::ERROR_BAD_MAGIC: return tr("File is the wrong type or corrupted"); case Texture::ERROR_UNSUPPORTED_VERSION: return tr("Unsupported version"); case Texture::ERROR_BAD_DATA: return tr("File contains invalid data"); case Texture::ERROR_UNEXPECTED_EOF: return tr("Unexpected end of file"); case Texture::ERROR_UNSUPPORTED_OPERATION: return tr("This operation is not supported"); case Texture::ERROR_BAD_ARGUMENT: return tr("Invalid argument (internal error)"); case Texture::ERROR_UNKNOWN: return tr("Unknown error"); default: break; } return QString("FIXME: Untranslated texture error"); } QString modelErrStr( Model::ModelErrorE err, Model * model ) { return g_errorObject.getModelErrorString( err, model ); } QString textureErrStr( Texture::ErrorE err ) { return g_errorObject.getTextureErrorString( err ); } mm3d-1.3.7/src/stdtexfilters.cc0000644000175000017500000000302210744511353013305 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "stdtexfilters.h" #include "texmgr.h" #include "pcxtex.h" #include "qttex.h" #include "tgatex.h" #include "rawtex.h" #include "log.h" int init_std_texture_filters() { log_debug( "initializing standard texture filters\n" ); TextureManager * textureManager = TextureManager::getInstance(); TextureFilter * filter; filter = new TgaTextureFilter; textureManager->registerTextureFilter( filter ); filter = new RawTextureFilter; textureManager->registerTextureFilter( filter ); filter = new PcxTextureFilter; textureManager->registerTextureFilter( filter ); filter = new QtTextureFilter; textureManager->registerTextureFilter( filter ); return 0; } mm3d-1.3.7/src/Makefile.in0000644000175000017500000004464411025503556012155 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = .. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = mm3d$(EXEEXT) subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am__objects_1 = am_mm3d_OBJECTS = 3dm.$(OBJEXT) stdcmds.$(OBJEXT) stdfilters.$(OBJEXT) \ stdtexfilters.$(OBJEXT) stdtools.$(OBJEXT) $(am__objects_1) mm3d_OBJECTS = $(am_mm3d_OBJECTS) am__DEPENDENCIES_1 = mm3d_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) tools/libtools.a \ commands/libcommands.a implui/libimplui.a qtui/libqtui.a \ depui/libdepui.a mm3dcore/libmm3dcore.a libmm3d/libmm3d.a DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(mm3d_SOURCES) DIST_SOURCES = $(mm3d_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ install-recursive installcheck-recursive installdirs-recursive \ pdf-recursive ps-recursive uninstall-info-recursive \ uninstall-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BYTEORDER = @BYTEORDER@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_PROFILE = @CORE_PROFILE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLOPEN_LIBS = @DLOPEN_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ HAVE_QT4 = @HAVE_QT4@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ LUALIB_CCFLAGS = @LUALIB_CCFLAGS@ LUALIB_DIR = @LUALIB_DIR@ LUALIB_LIBS = @LUALIB_LIBS@ LUA_CCFLAGS = @LUA_CCFLAGS@ LUA_DIR = @LUA_DIR@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PROFILE = @PROFILE@ QGL_LIBS = @QGL_LIBS@ QT_CXXFLAGS = @QT_CXXFLAGS@ QT_DIR = @QT_DIR@ QT_LIBS = @QT_LIBS@ QT_LRELEASE = @QT_LRELEASE@ QT_MOC = @QT_MOC@ QT_UIC = @QT_UIC@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ SUBDIRS = libmm3d mm3dcore depui qtui implui tools commands pixmap EXTRA_DIST = icon.rc maketags.sh mm3d_HFILES = \ stdcmds.h \ stdfilters.h \ stdtexfilters.h \ stdtools.h mm3d_SOURCES = \ 3dm.cc \ stdcmds.cc \ stdfilters.cc \ stdtexfilters.cc \ stdtools.cc \ $(mm3d_HFILES) mm3d_LDADD = $(CORE_PROFILE) $(QGL_LIBS) $(QT_LIBS) $(LUALIB_LIBS) $(GL_LIBS) $(DLOPEN_LIBS) tools/libtools.a commands/libcommands.a implui/libimplui.a qtui/libqtui.a depui/libdepui.a mm3dcore/libmm3dcore.a libmm3d/libmm3d.a -lgcov mm3d_LDFLAGS = $(all_libraries) $(QT_CXXFLAGS) AM_CPPFLAGS = $(CORE_PROFILE) -coverage -Wall -Ilibmm3d -Imm3dcore -Idepui -Iqtui -Iimplui -Itools -Icommands -DMM3D_EDIT $(all_includes) $(QT_CXXFLAGS) $(LUALIB_CCFLAGS) $(GL_CFLAGS) CLEANFILES = *.gcno *.gcda all: all-recursive .SUFFIXES: .SUFFIXES: .cc .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ rm -f "$(DESTDIR)$(bindir)/$$f"; \ done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) mm3d$(EXEEXT): $(mm3d_OBJECTS) $(mm3d_DEPENDENCIES) @rm -f mm3d$(EXEEXT) $(CXXLINK) $(mm3d_LDFLAGS) $(mm3d_OBJECTS) $(mm3d_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/3dm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdcmds.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdfilters.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdtexfilters.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stdtools.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` uninstall-info-am: # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" mostlyclean-recursive clean-recursive distclean-recursive \ maintainer-clean-recursive: @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(mkdir_p) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(mkdir_p) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-exec-am: install-binPROGRAMS install-info: install-info-recursive install-man: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-info-am uninstall-info: uninstall-info-recursive .PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ clean clean-binPROGRAMS clean-generic clean-recursive ctags \ ctags-recursive distclean distclean-compile distclean-generic \ distclean-recursive distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-exec install-exec-am \ install-info install-info-am install-man install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic \ maintainer-clean-recursive mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-recursive pdf pdf-am ps ps-am \ tags tags-recursive uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-info-am %.moc.cc: %.h $(QT_MOC) -o $@ $< wc: wc `ls *.h *.cpp *.cc *.y *.l */*.h */*.cpp */*.cc */*.y */*.l 2> /dev/null | grep -v moc.cc | grep -v "\.base\." ` | sort -n # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mm3d-1.3.7/src/stdtools.h0000644000175000017500000000167010744511353012125 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __STDTOOLS_H #define __STDTOOLS_H int init_std_tools(void); #endif // __STDTOOLS_H mm3d-1.3.7/src/libmm3d/0000777000175000017500000000000011031450273011501 500000000000000mm3d-1.3.7/src/libmm3d/weld.cc0000644000175000017500000001267610767317432012711 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "weld.h" #include "model.h" #include "glmath.h" #include "log.h" #include "msg.h" #include "modelstatus.h" #include #include using std::list; using std::map; // For unweld typedef struct _NewVertices_t { int index; int v[3]; bool selected[3]; } NewVerticesT; typedef std::list NewVerticesList; void weldSelectedVertices( Model * model, double tolerance ) { int dummy1 = 0; int dummy2 = 0; weldSelectedVertices( model, tolerance, dummy1, dummy2 ); } void weldSelectedVertices( Model * model, double tolerance, int & unweldnum, int & weldnum ) { list vert; model->getSelectedVertices( vert ); map welded; int weldSources = 0; int weldTargets = 0; list::iterator it; list::iterator it2; // Find vertices to weld and store in "welded" for ( it = vert.begin(); it != vert.end(); it++ ) { bool match = false; it2 = it; it2++; for ( ; it2 != vert.end(); it2++ ) { double a[3]; double b[3]; model->getVertexCoords( *it, a ); model->getVertexCoords( *it2, b ); double d = distance( a[0], a[1], a[2], b[0], b[1], b[2] ); if ( d < tolerance && welded.find( *it2 ) == welded.end() ) { log_debug( "weld vertices %d and %d\n", *it, *it2 ); welded[ *it2 ] = *it; match = true; weldSources++; } } if ( match ) { weldTargets++; } } // Move triangles to welded vertices for ( int t = 0; t < model->getTriangleCount(); t++ ) { int v[3]; bool changeVertices = false; for ( int i = 0; i < 3; i++ ) { v[i] = model->getTriangleVertex( t, i ); if ( welded.find(v[i]) != welded.end() ) { v[i] = welded[v[i]]; changeVertices = true; } } if ( changeVertices ) { model->setTriangleVertices( t, v[0], v[1], v[2] ); } } // Delete orphaned vertices map::reverse_iterator mit; model->deleteFlattenedTriangles(); model->deleteOrphanedVertices(); unweldnum = weldSources + weldTargets; weldnum = weldTargets; } void unweldSelectedVertices( Model * model ) { int dummy1 = 0; int dummy2 = 0; unweldSelectedVertices( model, dummy1, dummy2 ); } void unweldSelectedVertices( Model * model, int & unweldnum, int & weldnum ) { list vert; model->getSelectedVertices( vert ); NewVerticesList nvl; int added = 0; map vertCount; list::iterator it; for ( it = vert.begin(); it != vert.end(); it++ ) { vertCount[ *it ] = 0; } for ( int t = 0; t < model->getTriangleCount(); t++ ) { NewVerticesT nv; nv.index = t; bool changeVertices = false; for ( int i = 0; i < 3; i++ ) { nv.v[i] = model->getTriangleVertex( t, i ); if ( vertCount.find( nv.v[i] ) != vertCount.end() ) { nv.selected[i] = true; vertCount[ nv.v[i] ]++; if ( vertCount[ nv.v[i] ] > 1 ) { changeVertices = true; double coords[3]; model->getVertexCoords( nv.v[i], coords ); int temp = model->addVertex( coords[0], coords[1], coords[2] ); Model::InfluenceList inf; model->getVertexInfluences( nv.v[i], inf ); for ( Model::InfluenceList::const_iterator it = inf.begin(); it != inf.end(); ++it ) { model->addVertexInfluence( temp, it->m_boneId, it->m_type, it->m_weight ); } nv.v[i] = temp; added++; unweldnum++; } else { weldnum++; } } else { nv.selected[i] = false; } } nvl.push_back( nv ); } NewVerticesList::iterator nvit; for ( nvit = nvl.begin(); nvit != nvl.end(); nvit++ ) { model->setTriangleVertices( (*nvit).index, (*nvit).v[0], (*nvit).v[1], (*nvit).v[2] ); } list tri; model->getSelectedTriangles( tri ); model->unselectAll(); model->unselectAll(); for ( it = tri.begin(); it != tri.end(); it++ ) { model->selectTriangle( *it ); } for ( nvit = nvl.begin(); nvit != nvl.end(); nvit++ ) { for ( int i = 0; i < 3; i++ ) { if ( (*nvit).selected[i] ) { model->selectVertex( (*nvit).v[i] ); } } } unweldnum += weldnum; } mm3d-1.3.7/src/libmm3d/texmgr.cc0000644000175000017500000003427210744511346013253 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "texmgr.h" #include "log.h" #include "msg.h" #include "texscale.h" #include "mm3dport.h" #include "translate.h" #include #include #include #include #include using std::string; static bool _alreadyWarned = false; static bool _doWarning = false; void texture_manager_do_warning() { if ( _doWarning ) { msg_warning( transll( QT_TRANSLATE_NOOP( "LowLevel", "Model has a texture that is not powers of 2" )).c_str() ); _alreadyWarned = true; _doWarning = false; } } int TextureFilter::ImageData::s_allocated = 0; TextureFilter::ImageData::ImageData() : m_mustFree( false ), m_size( 0 ), m_data( NULL ) { s_allocated++; } TextureFilter::ImageData::~ImageData() { s_allocated--; if ( m_mustFree && m_data ) { delete[] m_data; m_data = NULL; m_mustFree = false; } } TextureFilter::ImageData * TextureFilter::ImageData::get( size_t dataSize, const uint8_t * dataPtr ) { ImageData * ptr = new ImageData(); ptr->m_size = dataSize; // Cast to non-const... I promise I won't change it! ptr->m_data = (uint8_t *) dataPtr; ptr->m_mustFree = false; if ( ptr->m_data == NULL && ptr->m_size != 0 ) { ptr->m_mustFree = true; ptr->m_data = new uint8_t[ ptr->m_size ]; } return ptr; } void TextureFilter::ImageData::release() { delete this; } uint8_t * TextureFilter::ImageData::getDataPtr() { if ( m_mustFree ) { return m_data; } else { return NULL; // Memory is read only! Call getConstDataPtr() instead. } } const uint8_t * TextureFilter::ImageData::getConstDataPtr() const { return m_data; } TextureManager * TextureManager::s_instance = NULL; TextureManager::TextureManager() { } TextureManager::~TextureManager() { log_debug( "TextureManager releasing %d textures and %d filters\n", m_textures.size(), m_filters.size() ); TextureList::iterator texIt = m_textures.begin(); while ( texIt != m_textures.end() ) { delete (*texIt); texIt++; } m_textures.clear(); TextureFilterList::iterator filterIt = m_filters.begin(); while ( filterIt != m_filters.end() ) { (*filterIt)->release(); filterIt++; } m_filters.clear(); } TextureManager * TextureManager::getInstance() { if ( s_instance == NULL ) { s_instance = new TextureManager(); } return s_instance; } void TextureManager::release() { if ( s_instance != NULL ) { delete s_instance; s_instance = NULL; } } void TextureManager::registerTextureFilter( TextureFilter * filter ) { m_filters.push_front( filter ); } Texture * TextureManager::getTexture( const char * filename, bool noCache ) { if ( filename == NULL ) { return NULL; } if( !noCache ) { TextureList::iterator texIt = m_textures.begin(); while ( texIt != m_textures.end() ) { if ( strcmp( filename, (*texIt)->m_filename ) == 0 ) { log_debug( "cached image %s\n", filename ); return *texIt; } texIt++; } } if ( filename[0] == '\0' ) { return getBlankTexture( "blank" ); } TextureFilterList::iterator filterIt = m_filters.begin(); Texture * newTexture = new Texture(); newTexture->m_isBad = false; while ( filterIt != m_filters.end() ) { if ( (*filterIt)->canRead( filename ) ) { Texture::ErrorE error; if ( (error = (*filterIt)->readFile( newTexture, filename )) == Texture::ERROR_NONE ) { m_lastError = Texture::ERROR_NONE; log_debug( "read from image file %s\n", filename ); struct stat statbuf; PORT_lstat( filename, &statbuf ); newTexture->m_loadTime = statbuf.st_mtime; newTexture->m_origWidth = newTexture->m_width; newTexture->m_origHeight = newTexture->m_height; if ( texture_scale_need_scale( newTexture->m_width, newTexture->m_height ) ) { _doWarning = true; uint8_t * oldData = newTexture->m_data; newTexture->m_data = texture_scale_auto( newTexture->m_data, newTexture->m_format, newTexture->m_width, newTexture->m_height ); delete[] oldData; } if( !noCache ) { m_textures.push_front( newTexture ); } return newTexture; } else { m_lastError = error; log_error( "filter could not read file: %d\n", error ); } } filterIt++; } delete newTexture; return NULL; } Texture * TextureManager::getTexture( const char * format, const TextureFilter::ImageData * d ) { if ( format == NULL || d == NULL ) { return NULL; } TextureFilterList::iterator filterIt = m_filters.begin(); Texture * newTexture = new Texture(); newTexture->m_isBad = false; std::string formatStr = std::string(".") + std::string( format ); log_debug( "finding filter for image in memory\n" ); while ( filterIt != m_filters.end() ) { if ( (*filterIt)->canRead( formatStr.c_str() ) ) { Texture::ErrorE error; log_debug( "found filter for format %s\n", format ); if ( (error = (*filterIt)->readMemory( format, newTexture, d )) == Texture::ERROR_NONE ) { m_lastError = Texture::ERROR_NONE; log_debug( "read from image memory\n" ); newTexture->m_origWidth = newTexture->m_width; newTexture->m_origHeight = newTexture->m_height; if ( texture_scale_need_scale( newTexture->m_width, newTexture->m_height ) ) { _doWarning = true; uint8_t * oldData = newTexture->m_data; newTexture->m_data = texture_scale_auto( newTexture->m_data, newTexture->m_format, newTexture->m_width, newTexture->m_height ); delete[] oldData; } m_textures.push_front( newTexture ); return newTexture; } else { m_lastError = error; log_error( "filter could not read memory: %d\n", error ); } } filterIt++; } delete newTexture; return NULL; } bool TextureManager::reloadTextures() { bool anyTextureChanged = false; TextureList::iterator texIter; for( texIter = m_textures.begin(); texIter != m_textures.end(); texIter++ ) { struct stat buf; if( PORT_lstat( (*texIter)->m_filename, &buf ) == 0 && buf.st_mtime > (*texIter)->m_loadTime ) { Texture *refreshedTexture = getTexture( (*texIter)->m_filename, true ); if( refreshedTexture ) { log_debug( "reloaded texture %s\n", (*texIter)->m_filename ); // Swap m_data pointers for new and old uint8_t * tempPtr = (*texIter)->m_data; (*texIter)->m_width = refreshedTexture->m_width; (*texIter)->m_height = refreshedTexture->m_height; (*texIter)->m_origWidth = refreshedTexture->m_origWidth; (*texIter)->m_origHeight = refreshedTexture->m_origHeight; (*texIter)->m_format = refreshedTexture->m_format; (*texIter)->m_data = refreshedTexture->m_data; (*texIter)->m_loadTime = buf.st_mtime; // new texture will clean up old data ptr. refreshedTexture->m_data = tempPtr; delete refreshedTexture; anyTextureChanged = true; } else { std::string msg = transll( QT_TRANSLATE_NOOP( "LowLevel", "Could not load" ) ); msg += std::string(" ") + (*texIter)->m_filename; msg_warning( msg.c_str() ); } } } return anyTextureChanged; } Texture * TextureManager::getBlankTexture( const char * name ) { TextureList::iterator texIt = m_textures.begin(); while ( texIt != m_textures.end() ) { if ( strcmp( name, "" ) == 0 ) { log_debug( "cached image (blank)\n" ); return *texIt; } texIt++; } Texture * tex = new Texture(); tex->m_isBad = false; tex->m_name = strdup( name ); tex->m_filename = strdup( "" ); tex->m_height = 2; tex->m_width = 2; tex->m_origHeight = tex->m_height; tex->m_origWidth = tex->m_width; tex->m_data = (uint8_t *) malloc( sizeof(uint8_t) * 4 * 4); for ( unsigned t = 0; t < 4 * 4; t++ ) { tex->m_data[ t ] = 0xFF; } m_textures.push_front( tex ); return tex; } Texture * TextureManager::getDefaultTexture( const char * filename ) { Texture * tex = new Texture(); tex->m_isBad = true; string str = string("bad: ") + filename; tex->m_name = strdup( str.c_str() ); tex->m_filename = strdup( str.c_str() ); tex->m_height = 8; tex->m_width = 8; tex->m_origWidth = tex->m_width; tex->m_origHeight = tex->m_height; tex->m_data = (uint8_t *) malloc( sizeof(uint8_t) * 4 * 64); char pattern[] = " x x x x x x x x x "; for ( int y = 0; y < tex->m_height; y++ ) { for ( int x = 0; x < tex->m_width; x++ ) { switch ( pattern[ y*8 + x ] ) { case ' ': tex->m_data[ (y*8 + x) * 4 + 0 ] = 0xFF; tex->m_data[ (y*8 + x) * 4 + 1 ] = 0x00; tex->m_data[ (y*8 + x) * 4 + 2 ] = 0x00; tex->m_data[ (y*8 + x) * 4 + 3 ] = 0xFF; break; case 'x': tex->m_data[ (y*8 + x) * 4 + 0 ] = 0x00; tex->m_data[ (y*8 + x) * 4 + 1 ] = 0x00; tex->m_data[ (y*8 + x) * 4 + 2 ] = 0x00; tex->m_data[ (y*8 + x) * 4 + 3 ] = 0xFF; break; default: break; } } } m_textures.push_front( tex ); return tex; } Texture::ErrorE TextureManager::writeFile( Texture * tex, const char * filename ) { if ( filename == NULL || filename[0] == '\0' || tex == NULL ) { return Texture::ERROR_BAD_ARGUMENT; } TextureFilterList::iterator filterIt = m_filters.begin(); while ( filterIt != m_filters.end() ) { if ( (*filterIt)->canWrite( filename ) ) { Texture::ErrorE error; if ( (error = (*filterIt)->writeFile( tex, filename )) == Texture::ERROR_NONE ) { m_lastError = Texture::ERROR_NONE; return Texture::ERROR_NONE; } else { m_lastError = error; log_error( "filter could not write file: %d\n", error ); } } filterIt++; } return Texture::ERROR_UNSUPPORTED_OPERATION; } bool TextureManager::canWrite( const char * filename ) { if ( filename == NULL || filename[0] == '\0' ) { return Texture::ERROR_BAD_ARGUMENT; } TextureFilterList::iterator filterIt = m_filters.begin(); while ( filterIt != m_filters.end() ) { if ( (*filterIt)->canWrite( filename ) ) { return true; } filterIt++; } return false; } Texture::ErrorE TextureManager::writeMemory( const char * format, Texture * tex, TextureFilter::ImageData ** d ) { if ( format == NULL || format[0] == '\0' || tex == NULL || d == NULL ) { return Texture::ERROR_BAD_ARGUMENT; } TextureFilterList::iterator filterIt = m_filters.begin(); log_debug( "finding filter for format %s\n", format ); std::string filename = std::string( "." ) + std::string( format ); while ( filterIt != m_filters.end() ) { if ( (*filterIt)->canWrite( filename.c_str() ) ) { log_debug( "found filter for format %s\n", format ); Texture::ErrorE error; if ( (error = (*filterIt)->writeMemory( format, tex, d )) == Texture::ERROR_NONE ) { m_lastError = Texture::ERROR_NONE; return Texture::ERROR_NONE; } else { m_lastError = error; log_error( "filter could not write memory: %d\n", error ); } } filterIt++; } return Texture::ERROR_UNSUPPORTED_OPERATION; } list TextureManager::getAllReadTypes() { list rval; TextureFilterList::iterator filterIt = m_filters.begin(); log_debug( "have %d filters\n", m_filters.size() ); while ( filterIt != m_filters.end() ) { list temp = (*filterIt)->getReadTypes(); while ( temp.size() ) { bool found = false; list::iterator sit; for ( sit = rval.begin(); sit != rval.end() && !found; sit++ ) { if ( *sit == temp.front() ) { found = true; } } if ( !found ) { string s = temp.front(); rval.push_back( s ); #ifndef WIN32 unsigned len = s.length(); for ( unsigned n = 0; n < len; n++ ) { if ( isupper( s[n] ) ) { s[n] = tolower( s[n] ); } else { s[n] = toupper( s[n] ); } } rval.push_back( s ); #endif // ! WIN32 } temp.pop_front(); } filterIt++; } return rval; } mm3d-1.3.7/src/libmm3d/filedatasource.h0000644000175000017500000000357210744511346014600 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef FILEDATASOURCE_INC_H__ #define FILEDATASOURCE_INC_H__ #include "datasource.h" #include #include #include #include // This class is a DataSource that uses a FILE* as the underlying input // source. See the documentation in datasource.h for the DataSource API. // The details below are specific to the FileDataSource and probably not // of direct interest to anyone writing model or texture import filters. class FileDataSource : public DataSource { public: // fp must be open for read and must be seekable FileDataSource( FILE * fp ); FileDataSource( const char * filename ); virtual ~FileDataSource(); void internalClose(); protected: virtual bool internalReadAt( off_t offset, const uint8_t ** buf, size_t * bufLen ); private: void sendErrno( int err ); enum { BUF_SIZE = 128 * 1024 // Arbitrary }; FILE * m_fp; bool m_mustClose; uint8_t m_buf[ BUF_SIZE ]; }; #endif // FILEDATASOURCE_INC_H__ mm3d-1.3.7/src/libmm3d/model.cc0000644000175000017500000033243010746733504013046 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "texmgr.h" #include "texture.h" #include "log.h" #ifdef MM3D_EDIT #include "modelstatus.h" #include "undomgr.h" #include "modelundo.h" #endif // MM3D_EDIT #include "translate.h" #include #include #include #include #include #include #include //#define MODEL_ANIMATION using std::map; using std::vector; #ifdef MM3D_EDIT typedef struct _SplitEdges_t { unsigned a; unsigned b; unsigned vNew; bool operator< ( const struct _SplitEdges_t & rhs ) const { return ( this->a < rhs.a || ( this->a == rhs.a && this->b < rhs.b ) ); }; bool operator== ( const struct _SplitEdges_t & rhs ) const { return ( this->a == rhs.a && this->b == rhs.b ); }; } SplitEdgesT; #endif // MM3D_EDIT // used to calculate smoothed normals in calculateNormals class NormAccum { public: NormAccum() { memset( norm, 0, sizeof(norm) ); } float norm[3]; }; // used to calculate smoothed normals in calculateNormals class NormAngleAccum { public: NormAngleAccum() { memset( norm, 0, sizeof(norm) ); angle = 0.0f; } NormAngleAccum( const NormAngleAccum & rhs ) : angle( rhs.angle ) { memcpy( norm, rhs.norm, sizeof(norm) ); } float norm[3]; float angle; }; std::string Model::s_lastFilterError = "No error"; static int _allocated = 0; const double TOLERANCE = 0.00005; const double ATOLERANCE = 0.00000001; // returns: // 1 = in front // 0 = on plane // -1 = in back static int _pointInPlane( double * coord, double * triCoord, double * triNorm ) { double btoa[3]; for ( int j = 0; j < 3; j++ ) { btoa[j] = coord[j] - triCoord[j]; } normalize3( btoa ); double c = dot3( btoa, triNorm ); if ( c < -ATOLERANCE ) return -1; else if ( c > ATOLERANCE ) return 1; else return 0; } // NOTE: Assumes coord is in plane of p1,p2,p3 // // returns: // 1 = inside triangle // 0 = on triangle edge // -1 = outside triangle static int _pointInTriangle( double * coord, double * p1, double * p2, double * p3 ) { int vside[3]; int i; double avg[3]; double normal[3]; for ( i = 0; i < 3; i++ ) { avg[i] = (p1[i] + p2[i] + p3[i]) / 3.0; } calculate_normal( normal, p1, p2, p3 ); for ( i = 0; i < 3; i++ ) { avg[i] += normal[i]; } calculate_normal( normal, p1, p2, avg ); vside[0] = _pointInPlane( coord, avg, normal ); calculate_normal( normal, p2, p3, avg ); vside[1] = _pointInPlane( coord, avg, normal ); calculate_normal( normal, p3, p1, avg ); vside[2] = _pointInPlane( coord, avg, normal ); if ( vside[0] < 0 && vside[1] < 0 && vside[2] < 0 ) { return 1; } if ( vside[0] > 0 && vside[1] > 0 && vside[2] > 0 ) { return 1; } if ( vside[0] == 0 && vside[1] == vside[2] ) { return 0; } if ( vside[1] == 0 && vside[0] == vside[2] ) { return 0; } if ( vside[2] == 0 && vside[0] == vside[1] ) { return 0; } if ( vside[0] == 0 && vside[1] == 0 ) { return 0; } if ( vside[0] == 0 && vside[2] == 0 ) { return 0; } if ( vside[1] == 0 && vside[2] == 0 ) { return 0; } return -1; } // returns: // ipoint = coordinates of edge line and plane // int = 0 is no intersection, +1 is toward p2 from p1, -1 is away from p2 from p1 static int _findEdgePlaneIntersection( double * ipoint, double * p1, double * p2, double * triCoord, double * triNorm ) { double edgeVec[3]; edgeVec[0] = p2[0] - p1[0]; edgeVec[1] = p2[1] - p1[1]; edgeVec[2] = p2[2] - p1[2]; /* log_debug( "finding intersection with plane with line from %f,%f,%f to %f,%f,%f\n", p1[0], p1[1], p1[2], p2[0], p2[1], p2[2] ); */ double a = dot3( edgeVec, triNorm ); double d = - dot3( triCoord, triNorm ); // prevent divide by zero if ( fabs(a) < TOLERANCE ) { // edge is parallel to plane, the value of ipoint is undefined return 0; } // distance along edgeVec p1 to plane double dist = -(d + dot3( p1, triNorm )) / a; // dist is % of velocity vector, scale to get impact point edgeVec[0] *= dist; edgeVec[1] *= dist; edgeVec[2] *= dist; ipoint[0] = p1[0] + edgeVec[0]; ipoint[1] = p1[1] + edgeVec[1]; ipoint[2] = p1[2] + edgeVec[2]; // Distance is irrelevant, we just want to know where // the intersection is if ( dist >= 0.0 ) { return 1; } else { return -1; } } Model::Observer::~Observer() { } Model::Model() : m_initialized( true ), m_filename( "" ), m_validBspTree( false ), m_canvasDrawMode( 0 ), m_drawJoints( JOINTMODE_BONES ), m_drawProjections( true ), m_validNormals( false ), m_validJoints( false ), m_forceAddOrDelete( false ), m_animationMode( ANIMMODE_NONE ), m_animationLoop( true ), m_currentFrame( 0 ), m_currentAnim( 0 ), m_currentTime( 0.0 ) #ifdef MM3D_EDIT , m_saved( true ), m_selectionMode( SelectVertices ), m_selecting( false ), m_changeBits( ChangeAll ), m_undoEnabled( false ) #endif // MM3D_EDIT { _allocated++; m_localMatrix.loadIdentity(); #ifdef MM3D_EDIT for ( unsigned t = 0; t < MAX_BACKGROUND_IMAGES; t++ ) { m_background[t] = new BackgroundImage(); } m_undoMgr = new UndoManager(); //m_animUndoMgr = new UndoManager(); #endif // MM3D_EDIT } Model::~Model() { m_bspTree.clear(); log_debug( "deleting model\n" ); DrawingContextList::iterator it; for ( it = m_drawingContexts.begin(); it != m_drawingContexts.end(); it++ ) { deleteGlTextures( (*it)->m_context ); } m_drawingContexts.clear(); while ( ! m_vertices.empty() ) { m_vertices.back()->release(); m_vertices.pop_back(); } while ( ! m_triangles.empty() ) { m_triangles.back()->release(); m_triangles.pop_back(); } while ( ! m_groups.empty() ) { m_groups.back()->release(); m_groups.pop_back(); } while ( ! m_materials.empty() ) { m_materials.back()->release(); m_materials.pop_back(); } while ( ! m_skelAnims.empty() ) { m_skelAnims.back()->release(); m_skelAnims.pop_back(); } while ( ! m_joints.empty() ) { m_joints.back()->release(); m_joints.pop_back(); } while ( ! m_points.empty() ) { m_points.back()->release(); m_points.pop_back(); } while ( ! m_projections.empty() ) { m_projections.back()->release(); m_projections.pop_back(); } while ( ! m_frameAnims.empty() ) { m_frameAnims.back()->release(); m_frameAnims.pop_back(); } #ifdef MM3D_EDIT for ( unsigned t = 0; t < 6; t++ ) { delete m_background[t]; m_background[t] = NULL; } delete m_undoMgr; //delete m_animUndoMgr; #endif // MM3D_EDIT _allocated--; } const char * Model::errorToString( Model::ModelErrorE e, Model * model ) { switch ( e ) { case ERROR_NONE: return QT_TRANSLATE_NOOP( "LowLevel", "Success" ); case ERROR_CANCEL: return QT_TRANSLATE_NOOP( "LowLevel", "Canceled" ); case ERROR_UNKNOWN_TYPE: return QT_TRANSLATE_NOOP( "LowLevel", "Unrecognized file extension (unknown type)" ); case ERROR_UNSUPPORTED_OPERATION: return QT_TRANSLATE_NOOP( "LowLevel", "Operation not supported for this file type" ); case ERROR_BAD_ARGUMENT: return QT_TRANSLATE_NOOP( "LowLevel", "Invalid argument (internal error, probably null pointer argument)" ); case ERROR_NO_FILE: return QT_TRANSLATE_NOOP( "LowLevel", "File does not exist" ); case ERROR_NO_ACCESS: return QT_TRANSLATE_NOOP( "LowLevel", "Permission denied" ); case ERROR_FILE_OPEN: return QT_TRANSLATE_NOOP( "LowLevel", "Could not open file" ); case ERROR_FILE_READ: return QT_TRANSLATE_NOOP( "LowLevel", "Could not read from file" ); case ERROR_BAD_MAGIC: return QT_TRANSLATE_NOOP( "LowLevel", "File is the wrong type or corrupted" ); case ERROR_UNSUPPORTED_VERSION: return QT_TRANSLATE_NOOP( "LowLevel", "Unsupported version" ); case ERROR_BAD_DATA: return QT_TRANSLATE_NOOP( "LowLevel", "File contains invalid data" ); case ERROR_UNEXPECTED_EOF: return QT_TRANSLATE_NOOP( "LowLevel", "Unexpected end of file" ); case ERROR_EXPORT_ONLY: return QT_TRANSLATE_NOOP( "LowLevel", "Write not supported, try \"Export...\"" ); case ERROR_FILTER_SPECIFIC: if ( model ) { return model->getFilterSpecificError(); } else { return getLastFilterSpecificError(); } case ERROR_UNKNOWN: return QT_TRANSLATE_NOOP( "LowLevel", "Unknown error" ); } return QT_TRANSLATE_NOOP( "LowLevel", "Invalid error code" ); } bool Model::operationFailed( Model::ModelErrorE err ) { return (err != ERROR_NONE && err != ERROR_CANCEL ); } void Model::pushError( const std::string & err ) { m_loadErrors.push_back( err ); } std::string Model::popError() { std::string rval = ""; if ( !m_loadErrors.empty() ) { rval = m_loadErrors.front(); m_loadErrors.pop_front(); } return rval; } #ifdef MM3D_EDIT void Model::updateObservers() { for ( ObserverList::iterator it = m_observers.begin(); it != m_observers.end(); it++ ) { (*it)->modelChanged( m_changeBits ); } m_changeBits = 0; } void Model::addObserver( Model::Observer * o ) { m_observers.push_back( o ); } void Model::removeObserver( Model::Observer * o ) { ObserverList::iterator it; for ( it = m_observers.begin(); it != m_observers.end(); it++ ) { if ( *it == o ) { m_observers.erase( it ); return; } } } void Model::setUndoSizeLimit( unsigned sizeLimit ) { m_undoMgr->setSizeLimit( sizeLimit ); } void Model::setUndoCountLimit( unsigned countLimit ) { m_undoMgr->setCountLimit( countLimit ); } bool Model::isVertexVisible( unsigned v ) const { LOG_PROFILE(); if ( v < m_vertices.size() ) { return m_vertices[v]->m_visible; } else { return false; } } bool Model::isTriangleVisible( unsigned v ) const { LOG_PROFILE(); if ( v < m_triangles.size() ) { return m_triangles[v]->m_visible; } else { return false; } } bool Model::isGroupVisible( unsigned v ) const { LOG_PROFILE(); if ( v < m_groups.size() ) { return m_groups[v]->m_visible; } else { return false; } } bool Model::isBoneJointVisible( unsigned j ) const { LOG_PROFILE(); if ( j < m_joints.size() ) { return m_joints[j]->m_visible; } else { return false; } } bool Model::isPointVisible( unsigned p ) const { LOG_PROFILE(); if ( p < m_points.size() ) { return m_points[p]->m_visible; } else { return false; } } int Model::addVertex( double x, double y, double z ) { if ( m_animationMode ) { return -1; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return -1; } int num = m_vertices.size(); m_changeBits |= AddGeometry; Vertex * vertex = Vertex::get(); vertex->m_coord[0] = x; vertex->m_coord[1] = y; vertex->m_coord[2] = z; vertex->m_free = false; m_vertices.push_back( vertex ); MU_AddVertex * undo = new MU_AddVertex(); undo->addVertex( num, vertex ); sendUndo( undo ); return num; } void Model::setVertexFree( unsigned v, bool o ) { if (v < m_vertices.size() ) { m_vertices[v]->m_free = o; } } bool Model::isVertexFree( unsigned v ) const { if (v < m_vertices.size() ) { return m_vertices[v]->m_free; } return false; } int Model::addTriangle( unsigned v1, unsigned v2, unsigned v3 ) { if ( m_animationMode ) { return -1; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return -1; } m_changeBits |= AddGeometry; if ( v1 < m_vertices.size() && v2 < m_vertices.size() && v3 < m_vertices.size() ) { int num = m_triangles.size(); //log_debug( "adding triangle %d for vertices %d,%d,%d\n", num, v1, v2, v3 ); Triangle * triangle = Triangle::get(); triangle->m_vertexIndices[0] = v1; triangle->m_vertexIndices[1] = v2; triangle->m_vertexIndices[2] = v3; m_triangles.push_back( triangle ); invalidateNormals(); MU_AddTriangle * undo = new MU_AddTriangle(); undo->addTriangle( num, triangle ); sendUndo( undo ); return num; } else { return -1; } } int Model::addBoneJoint( const char * name, double x, double y, double z, double xrot, double yrot, double zrot, int parent ) { if ( m_animationMode || name == NULL || parent >= (int) m_joints.size() ) { return -1; } m_changeBits |= AddOther; int num = m_joints.size(); Joint * joint = Joint::get(); joint->m_parent = parent; joint->m_name = name; double trans[3] = { x, y, z }; double rot[3] = { xrot, yrot, zrot }; log_debug( "New joint at %f,%f,%f\n", x, y, z ); joint->m_absolute.loadIdentity(); joint->m_absolute.setRotation( rot ); joint->m_absolute.setTranslation( trans ); if ( parent >= 0 ) { m_joints[ parent ]->m_absolute.inverseTranslateVector( trans ); m_joints[ parent ]->m_absolute.inverseRotateVector( trans ); Matrix minv = m_joints[ parent ]->m_absolute.getInverse(); Matrix mr; mr.setRotation( rot ); mr = mr * minv; mr.getRotation( rot ); } for ( int t = 0; t < 3; t++ ) { joint->m_localTranslation[t] = trans[t]; joint->m_localRotation[t] = rot[t]; } //joint->m_localRotation[0] = xrot; //joint->m_localRotation[1] = yrot; //joint->m_localRotation[2] = zrot; //m_joints.push_back( joint ); num = m_joints.size(); insertBoneJoint( num, joint ); setupJoints(); MU_AddBoneJoint * undo = new MU_AddBoneJoint(); undo->addBoneJoint( num, joint ); sendUndo( undo ); return num; } int Model::addPoint( const char * name, double x, double y, double z, double xrot, double yrot, double zrot, int boneId ) { if ( m_animationMode || name == NULL || boneId >= (int) m_joints.size()) { return -1; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return -1; } m_changeBits |= AddOther; int num = m_points.size(); log_debug( "New point at %f,%f,%f\n", x, y, z ); Point * point = Point::get(); point->m_name = name; point->m_trans[0] = x; point->m_trans[1] = y; point->m_trans[2] = z; point->m_rot[0] = xrot; point->m_rot[1] = yrot; point->m_rot[2] = zrot; num = m_points.size(); insertPoint( num, point ); MU_AddPoint * undo = new MU_AddPoint(); undo->addPoint( num, point ); sendUndo( undo ); setupJoints(); return num; } int Model::addProjection( const char * name, int type, double x, double y, double z ) { if ( m_animationMode || name == NULL ) { return -1; } m_changeBits |= AddOther; int num = m_projections.size(); log_debug( "New projection at %f,%f,%f\n", x, y, z ); TextureProjection * proj = TextureProjection::get(); proj->m_name = name; proj->m_type = type; proj->m_pos[0] = x; proj->m_pos[1] = y; proj->m_pos[2] = z; proj->m_upVec[0] = 0.0; proj->m_upVec[1] = 1.0; proj->m_upVec[2] = 0.0; proj->m_seamVec[0] = 0.0; proj->m_seamVec[1] = 0.0; proj->m_seamVec[2] = -1.0; proj->m_range[0][0] = 0.0; // min x proj->m_range[0][1] = 0.0; // min y proj->m_range[1][0] = 1.0; // max x proj->m_range[1][1] = 1.0; // max y insertProjection( num, proj ); MU_AddProjection * undo = new MU_AddProjection(); undo->addProjection( num, proj ); sendUndo( undo ); return num; } bool Model::setTriangleVertices( unsigned triangleNum, unsigned vert1, unsigned vert2, unsigned vert3 ) { if ( m_animationMode ) { return false; } unsigned vertexCount = m_vertices.size(); if ( triangleNum < m_triangles.size() && (vert1 < vertexCount && vert2 < vertexCount && vert3 < vertexCount ) ) { MU_SetTriangleVertices * undo = new MU_SetTriangleVertices(); undo->setTriangleVertices( triangleNum, vert1, vert2, vert3, m_triangles[ triangleNum ]->m_vertexIndices[0], m_triangles[ triangleNum ]->m_vertexIndices[1], m_triangles[ triangleNum ]->m_vertexIndices[2] ); sendUndo( undo ); m_triangles[triangleNum]->m_vertexIndices[0] = vert1; m_triangles[triangleNum]->m_vertexIndices[1] = vert2; m_triangles[triangleNum]->m_vertexIndices[2] = vert3; invalidateNormals(); return true; } else { return false; } } bool Model::getTriangleVertices( unsigned triangleNum, unsigned & vert1, unsigned & vert2, unsigned & vert3 ) const { if ( triangleNum < m_triangles.size() ) { vert1 = m_triangles[ triangleNum ] ->m_vertexIndices[0]; vert2 = m_triangles[ triangleNum ] ->m_vertexIndices[1]; vert3 = m_triangles[ triangleNum ] ->m_vertexIndices[2]; return true; } else { return false; } } void Model::deleteVertex( unsigned vertexNum ) { LOG_PROFILE(); if ( m_animationMode ) { return; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return; } if ( vertexNum >= m_vertices.size() ) { return; } MU_DeleteVertex * undo = new MU_DeleteVertex(); undo->deleteVertex( vertexNum, m_vertices[vertexNum] ); sendUndo( undo ); removeVertex( vertexNum ); } void Model::deleteTriangle( unsigned triangleNum ) { LOG_PROFILE(); if ( m_animationMode ) { return; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return; } if ( triangleNum >= m_triangles.size() ) { return; } // remove it from any groups for ( unsigned g = 0; g < m_groups.size(); g++ ) { removeTriangleFromGroup( g, triangleNum ); } // Delete triangle MU_DeleteTriangle * undo = new MU_DeleteTriangle(); undo->deleteTriangle( triangleNum, m_triangles[ triangleNum ] ); sendUndo( undo ); removeTriangle( triangleNum ); } void Model::deleteBoneJoint( unsigned joint ) { if ( joint < m_joints.size() ) { unsigned count = m_joints.size(); // Break out early if this is a root joint and it has a child if ( m_joints[joint]->m_parent < 0 ) { for ( unsigned j = 0; j < count; j++ ) { if ( j != joint ) { if ( m_joints[j]->m_parent == (int) joint ) { model_status( this, StatusError, STATUSTIME_LONG, transll( QT_TRANSLATE_NOOP( "LowLevel", "Cannot delete root joint" )).c_str() ); return; } } } } for ( unsigned v = 0; v < m_vertices.size(); v++ ) { removeVertexInfluence( v, joint ); } for ( unsigned p = 0; p < m_points.size(); p++ ) { removePointInfluence( p, joint ); } Matrix m; int parent = joint; do { parent = m_joints[ parent ]->m_parent; } while ( parent >= 0 && m_joints[ parent ]->m_selected ); if ( parent >= 0 ) { m = m_joints[ m_joints[joint]->m_parent ]->m_absolute.getInverse(); } for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_parent == (int) joint ) { setBoneJointParent( j, m_joints[joint]->m_parent ); m_joints[j]->m_absolute = m_joints[j]->m_absolute * m; double rot[3]; double trans[3]; m_joints[j]->m_absolute.getRotation( rot ); m_joints[j]->m_absolute.getTranslation( trans ); setBoneJointRotation( j, rot ); setBoneJointTranslation( j, trans ); } } Joint * ptr = m_joints[joint]; removeBoneJoint( joint ); m_validJoints = false; MU_DeleteBoneJoint * undo = new MU_DeleteBoneJoint(); undo->deleteBoneJoint( joint, ptr ); sendUndo( undo ); log_debug( "parent was %d\n", parent ); setupJoints(); } } void Model::deletePoint( unsigned point ) { if ( m_animationMode ) { return; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return; } if ( point < m_points.size() ) { Point * ptr = m_points[point]; removePoint( point ); MU_DeletePoint * undo = new MU_DeletePoint(); undo->deletePoint( point, ptr ); sendUndo( undo ); setupJoints(); } } void Model::deleteProjection( unsigned proj ) { if ( m_animationMode ) { return; } if ( proj < m_projections.size() ) { TextureProjection * ptr = m_projections[ proj ]; removeProjection( proj ); MU_DeleteProjection * undo = new MU_DeleteProjection(); undo->deleteProjection( proj, ptr ); sendUndo( undo ); } } void Model::deleteOrphanedVertices() { LOG_PROFILE(); if ( m_animationMode ) { return; } for ( unsigned v = 0; v < m_vertices.size(); v++ ) { m_vertices[v]->m_marked = false; } for ( unsigned t = 0; t< m_triangles.size(); t++ ) { for ( unsigned v = 0; v < 3; v++ ) { m_vertices[ m_triangles[t]->m_vertexIndices[v] ]->m_marked = true; } } for ( int v = m_vertices.size() - 1; v >= 0; v-- ) { if ( ! m_vertices[v]->m_marked && ! m_vertices[v]->m_free ) { deleteVertex( v ); } } } void Model::deleteFlattenedTriangles() { LOG_PROFILE(); // Delete any triangles that have two or more vertex indices that point // at the same vertex (could happen as a result of welding vertices if ( m_animationMode ) { return; } int count = m_triangles.size(); for ( int t = count-1; t >= 0; t-- ) { if ( m_triangles[t]->m_vertexIndices[0] == m_triangles[t]->m_vertexIndices[1] || m_triangles[t]->m_vertexIndices[0] == m_triangles[t]->m_vertexIndices[2] || m_triangles[t]->m_vertexIndices[1] == m_triangles[t]->m_vertexIndices[2] ) { deleteTriangle( t ); } } } void Model::deleteSelected() { LOG_PROFILE(); if ( m_animationMode ) { m_changeBits |= MoveGeometry; if ( m_animationMode == ANIMMODE_SKELETAL && m_currentAnim < m_skelAnims.size() && m_currentFrame < m_skelAnims[ m_currentAnim ]->m_frameCount ) { for ( int j = m_joints.size() - 1; j >= 0; j-- ) { if ( m_joints[j]->m_selected ) { deleteSkelAnimKeyframe( m_currentAnim, m_currentFrame, j, true ); deleteSkelAnimKeyframe( m_currentAnim, m_currentFrame, j, false ); } } } return; } m_changeBits |= AddGeometry; for ( int v = m_vertices.size() - 1; v >= 0; v-- ) { m_vertices[v]->m_marked = false; } for ( int t = m_triangles.size() - 1; t >= 0; t-- ) { if ( m_triangles[t]->m_selected ) { m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_marked = true; m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_marked = true; m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_marked = true; deleteTriangle( t ); } } for ( int t = m_triangles.size() - 1; t >= 0; t-- ) { if ( m_triangles[t]->m_visible ) { for ( int v = 0; v < 3; v++ ) { if ( m_vertices[ m_triangles[t]->m_vertexIndices[v] ]->m_selected && !m_vertices[ m_triangles[t]->m_vertexIndices[v] ]->m_marked ) { deleteTriangle( t ); break; } } } } for ( int v = m_vertices.size() - 1; v >= 0; v-- ) { if ( m_vertices[v]->m_selected && !m_vertices[v]->m_marked ) { deleteVertex( v ); } } deleteOrphanedVertices(); bool doJointSetup = false; for ( int j = m_joints.size() - 1; j >= 0; j-- ) { if ( m_joints[j]->m_selected ) { deleteBoneJoint( j ); doJointSetup = true; } } for ( int p = m_points.size() - 1; p >= 0; p-- ) { if ( m_points[p]->m_selected ) { deletePoint( p ); } } for ( int r = m_projections.size() - 1; r >= 0; r-- ) { if ( m_projections[r]->m_selected ) { deleteProjection( r ); } } // Some selected vertices may not be deleted if their parent // triangle was deleted unselectAll(); } bool Model::movePosition( const Position & pos, double x, double y, double z ) { switch ( pos.type ) { case PT_Vertex: return moveVertex( pos.index, x, y, z ); case PT_Joint: return moveBoneJoint( pos.index, x, y, z ); case PT_Point: return movePoint( pos.index, x, y, z ); case PT_Projection: return moveProjection( pos.index, x, y, z ); default: log_error( "do not know how to move position of type %d\n", pos.type ); break; } return false; } bool Model::moveVertex( unsigned v, double x, double y, double z ) { switch ( m_animationMode ) { case ANIMMODE_NONE: if ( v < m_vertices.size() ) { double old[3]; old[0] = m_vertices[v]->m_coord[0]; old[1] = m_vertices[v]->m_coord[1]; old[2] = m_vertices[v]->m_coord[2]; m_vertices[v]->m_coord[0] = x; m_vertices[v]->m_coord[1] = y; m_vertices[v]->m_coord[2] = z; invalidateNormals(); MU_MovePrimitive * undo = new MU_MovePrimitive; undo->addMovePrimitive( MU_MovePrimitive::MT_Vertex, v, x, y, z, old[0], old[1], old[2] ); sendUndo( undo, true ); return true; } break; case ANIMMODE_FRAME: if ( v < m_vertices.size() && m_currentAnim < m_frameAnims.size() ) { setFrameAnimVertexCoords( m_currentAnim, m_currentFrame, v, x, y, z ); return true; } break; default: break; } return false; } bool Model::moveBoneJoint( unsigned j, double x, double y, double z ) { if ( m_animationMode == ANIMMODE_NONE && j < m_joints.size() ) { MU_MovePrimitive * undo = new MU_MovePrimitive; undo->addMovePrimitive( MU_MovePrimitive::MT_Joint, j, x, y, z, m_joints[j]->m_absolute.get(3, 0), m_joints[j]->m_absolute.get(3, 1), m_joints[j]->m_absolute.get(3, 2) ); sendUndo( undo, true ); bool rval = relocateBoneJoint( j, x, y, z ); setupJoints(); return rval; } else { return false; } } bool Model::movePoint( unsigned p, double x, double y, double z ) { if ( m_animationMode == ANIMMODE_NONE && p < m_points.size() ) { MU_MovePrimitive * undo = new MU_MovePrimitive; undo->addMovePrimitive( MU_MovePrimitive::MT_Point, p, x, y, z, m_points[p]->m_trans[0], m_points[p]->m_trans[1], m_points[p]->m_trans[2] ); sendUndo( undo, true ); m_points[p]->m_trans[0] = x; m_points[p]->m_trans[1] = y; m_points[p]->m_trans[2] = z; return true; } else if ( m_animationMode == ANIMMODE_FRAME ) { setFrameAnimPointCoords( m_currentAnim, m_currentFrame, p, x, y, z ); return true; } else { log_debug("point %d does not exist\n", p ); return false; } } bool Model::relocateBoneJoint( unsigned j, double x, double y, double z ) { if ( j < m_joints.size() ) { double old[3]; double diff[3]; double tran[3]; old[0] = m_joints[j]->m_absolute.get(3, 0); old[1] = m_joints[j]->m_absolute.get(3, 1); old[2] = m_joints[j]->m_absolute.get(3, 2); tran[0] = diff[0] = (x - old[0]); tran[1] = diff[1] = (y - old[1]); tran[2] = diff[2] = (z - old[2]); if ( m_joints[j]->m_parent >= 0 ) { m_joints[ m_joints[j]->m_parent ]->m_absolute.inverseRotateVector( tran ); } m_joints[j]->m_localTranslation[0] += tran[0]; m_joints[j]->m_localTranslation[1] += tran[1]; m_joints[j]->m_localTranslation[2] += tran[2]; for ( unsigned t = 0; t < m_joints.size(); t++ ) { if ( m_joints[t]->m_parent == (signed) j ) { tran[0] = diff[0]; tran[1] = diff[1]; tran[2] = diff[2]; m_joints[ m_joints[t]->m_parent ]->m_absolute.inverseRotateVector( tran ); m_joints[t]->m_localTranslation[0] -= tran[0]; m_joints[t]->m_localTranslation[1] -= tran[1]; m_joints[t]->m_localTranslation[2] -= tran[2]; } } m_validJoints = false; return true; } else { return false; } } void Model::beginHideDifference() { LOG_PROFILE(); if ( m_undoEnabled ) { unsigned t; for ( t = 0; t < m_vertices.size(); t++ ) { m_vertices[t]->m_marked = m_vertices[t]->m_visible; } for ( t = 0; t < m_triangles.size(); t++ ) { m_triangles[t]->m_marked = m_triangles[t]->m_visible; } } } void Model::endHideDifference() { LOG_PROFILE(); if ( m_undoEnabled ) { switch ( m_selectionMode ) { case SelectVertices: { MU_Hide * undo = new MU_Hide( SelectVertices ); for ( unsigned t = 0; t < m_vertices.size(); t++ ) { if ( m_vertices[t]->m_visible != m_vertices[t]->m_marked ) { undo->setHideDifference( t, m_vertices[t]->m_visible ); } } sendUndo( undo ); } break; case SelectTriangles: case SelectGroups: { MU_Hide * undo = new MU_Hide( SelectTriangles ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_visible != m_triangles[t]->m_marked ) { undo->setHideDifference( t, m_triangles[t]->m_visible ); } } sendUndo( undo ); } break; default: break; } } } void Model::translateSelected( const Matrix & m ) { LOG_PROFILE(); list newJointList; m_changeBits |= MoveGeometry; if ( m_animationMode ) { if ( m_animationMode == ANIMMODE_SKELETAL ) { for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_selected && !parentJointSelected(j) ) { Matrix cur = m_joints[j]->m_final; Matrix absInv = m_joints[j]->m_absolute.getInverse(); cur = cur * m; if ( m_joints[j]->m_parent >= 0 ) { Joint * parent = m_joints[ m_joints[j]->m_parent ]; absInv = m_joints[j]->m_relative * parent->m_final; absInv = absInv.getInverse(); } cur = cur * absInv; double coords[3] = { 0,0,0 }; cur.getTranslation( coords ); setSkelAnimKeyframe( m_currentAnim, m_currentFrame, j, false, coords[0], coords[1], coords[2] ); } } setCurrentAnimationFrame( m_currentFrame ); // setSkelAnimKeyframe handles undo } else { if ( m_currentAnim < m_frameAnims.size() && m_currentFrame < m_frameAnims[ m_currentAnim ]->m_frameData.size() ) { vector & vertices = (*m_frameAnims[ m_currentAnim ]->m_frameData[ m_currentFrame ]->m_frameVertices); for ( unsigned v = 0; v < vertices.size(); v++ ) { if ( m_vertices[ v ]->m_selected ) { double coord[3]; getFrameAnimVertexCoords( m_currentAnim, m_currentFrame, v, coord[0], coord[1], coord[2] ); Vector vec( vertices[v]->m_coord ); vec.translate( m ); const double * val = vec.getVector(); setFrameAnimVertexCoords( m_currentAnim, m_currentFrame, v, val[0], val[1], val[2] ); } } for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_selected ) { double coord[3]; getFrameAnimPointCoords( m_currentAnim, m_currentFrame, p, coord[0], coord[1], coord[2] ); Vector vec( coord ); vec.translate( m ); const double * val = vec.getVector(); setFrameAnimPointCoords( m_currentAnim, m_currentFrame, p, val[0], val[1], val[2] ); } } } } } else { bool vertices = false; bool joints = false; for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[ v ]->m_selected ) { Vector vec( m_vertices[v]->m_coord ); vec.translate( m ); const double * val = vec.getVector(); m_vertices[v]->m_coord[0] = val[0]; m_vertices[v]->m_coord[1] = val[1]; m_vertices[v]->m_coord[2] = val[2]; vertices = true; } } for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_selected ) { double tran[3]; double diff[3]; tran[0] = diff[0] = m.get(3,0); tran[1] = diff[1] = m.get(3,1); tran[2] = diff[2] = m.get(3,2); if ( m_joints[j]->m_parent >= 0 ) { m_joints[ m_joints[j]->m_parent ]->m_absolute.inverseRotateVector( tran ); } m_joints[j]->m_localTranslation[0] += tran[0]; m_joints[j]->m_localTranslation[1] += tran[1]; m_joints[j]->m_localTranslation[2] += tran[2]; for ( unsigned t = 0; t < m_joints.size(); t++ ) { if ( m_joints[t]->m_parent == (signed) j ) { tran[0] = diff[0]; tran[1] = diff[1]; tran[2] = diff[2]; m_joints[ m_joints[t]->m_parent ]->m_absolute.inverseRotateVector( tran ); m_joints[t]->m_localTranslation[0] -= tran[0]; m_joints[t]->m_localTranslation[1] -= tran[1]; m_joints[t]->m_localTranslation[2] -= tran[2]; } } joints = true; } } for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_selected ) { m_points[p]->m_trans[0] += m.get( 3, 0 ); m_points[p]->m_trans[1] += m.get( 3, 1 ); m_points[p]->m_trans[2] += m.get( 3, 2 ); joints = true; } } for ( unsigned p = 0; p < m_projections.size(); p++ ) { if ( m_projections[p]->m_selected ) { m_projections[p]->m_pos[0] += m.get( 3, 0 ); m_projections[p]->m_pos[1] += m.get( 3, 1 ); m_projections[p]->m_pos[2] += m.get( 3, 2 ); applyProjection( p ); } } if ( vertices ) { invalidateNormals(); } if ( joints ) { setupJoints(); } MU_TranslateSelected * undo = new MU_TranslateSelected(); undo->setMatrix( m ); sendUndo( undo, true ); } } void Model::rotateSelected( const Matrix & m, double * point ) { LOG_PROFILE(); m_changeBits |= MoveGeometry; if ( m_animationMode ) { if ( m_animationMode == ANIMMODE_SKELETAL ) { unsigned joint = 0; for ( joint = 0; joint < m_joints.size(); joint++ ) { if ( m_joints[ joint ]->m_selected ) { Matrix cur = m_joints[joint]->m_final; Matrix absInv = m_joints[joint]->m_absolute.getInverse(); cur = cur * m; if ( m_joints[joint]->m_parent >= 0 ) { Joint * parent = m_joints[ m_joints[joint]->m_parent ]; absInv = m_joints[joint]->m_relative * parent->m_final; absInv = absInv.getInverse(); } cur = cur * absInv; double rot[3] = { 0,0,0 }; cur.getRotation( rot ); setSkelAnimKeyframe( m_currentAnim, m_currentFrame, joint, true, rot[0], rot[1], rot[2] ); setCurrentAnimationFrame( m_currentFrame ); // setSkelAnimKeyframe handles undo // TODO: should I really allow multiple joints here? //break; } } } else if ( m_animationMode == ANIMMODE_FRAME ) { for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[ v ]->m_selected ) { double coord[3]; getFrameAnimVertexCoords( m_currentAnim, m_currentFrame, v, coord[0], coord[1], coord[2] ); coord[0] -= point[0]; coord[1] -= point[1]; coord[2] -= point[2]; Vector vec( coord ); vec.translate( m ); coord[0] = vec[0]; coord[1] = vec[1]; coord[2] = vec[2]; coord[0] += point[0]; coord[1] += point[1]; coord[2] += point[2]; setFrameAnimVertexCoords( m_currentAnim, m_currentFrame, v, coord[0], coord[1], coord[2] ); } } for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_selected ) { double coord[3]; double rot[3]; getFrameAnimPointCoords( m_currentAnim, m_currentFrame, p, coord[0], coord[1], coord[2] ); getFrameAnimPointRotation( m_currentAnim, m_currentFrame, p, rot[0], rot[1], rot[2] ); /* coord[0] -= point[0]; coord[1] -= point[1]; coord[2] -= point[2]; */ Matrix pm; pm.setTranslation( coord[0] - point[0], coord[1] - point[1], coord[2] - point[2] ); pm.setRotation( rot ); pm = pm * m; pm.getTranslation( coord ); pm.getRotation( rot ); coord[0] += point[0]; coord[1] += point[1]; coord[2] += point[2]; setFrameAnimPointCoords( m_currentAnim, m_currentFrame, p, coord[0], coord[1], coord[2] ); setFrameAnimPointRotation( m_currentAnim, m_currentFrame, p, rot[0], rot[1], rot[2] ); } } } } else { Matrix inv = m.getInverse(); for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[ v ]->m_selected ) { m_vertices[v]->m_coord[0] -= point[0]; m_vertices[v]->m_coord[1] -= point[1]; m_vertices[v]->m_coord[2] -= point[2]; Vector vec( m_vertices[v]->m_coord ); vec.translate( m ); const double * val = vec.getVector(); m_vertices[v]->m_coord[0] = val[0]; m_vertices[v]->m_coord[1] = val[1]; m_vertices[v]->m_coord[2] = val[2]; m_vertices[v]->m_coord[0] += point[0]; m_vertices[v]->m_coord[1] += point[1]; m_vertices[v]->m_coord[2] += point[2]; } } for ( unsigned j = 0; j < m_joints.size(); j++ ) { // NOTE: This code assumes that if a bone joint is rotated, // all children are rotated with it. That may not be what // the user expects. To prevent this I would have to find // unselected joints whose direct parent was selected // and invert the operation on those joints. if ( m_joints[j]->m_selected && !parentJointSelected(j) ) { Joint * joint = m_joints[j]; Matrix trans; trans.setTranslation( point ); joint->m_absolute = joint->m_absolute * trans.getInverse(); joint->m_absolute = joint->m_absolute * m; joint->m_absolute = joint->m_absolute * trans; joint->m_absolute.getTranslation( joint->m_localTranslation ); if ( joint->m_parent >= 0 ) { Matrix pinv = m_joints[ joint->m_parent ]->m_absolute.getInverse(); Vector v( joint->m_localTranslation ); v = v * pinv; joint->m_localTranslation[0] = v.get(0); joint->m_localTranslation[1] = v.get(1); joint->m_localTranslation[2] = v.get(2); //pinv.apply3( joint->m_localTranslation ); Matrix mr = joint->m_absolute * pinv; mr.getRotation( joint->m_localRotation ); } else { joint->m_absolute.getRotation( joint->m_localRotation ); } } } for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_selected ) { Point * pnt = m_points[p]; Matrix pm; pm.setTranslation( pnt->m_trans[0] - point[0], pnt->m_trans[1] - point[1], pnt->m_trans[2] - point[2] ); pm.setRotation( pnt->m_rot ); pm = pm * m; pm.getTranslation( pnt->m_trans ); pm.getRotation( pnt->m_rot ); pnt->m_trans[0] += point[0]; pnt->m_trans[1] += point[1]; pnt->m_trans[2] += point[2]; } } for ( unsigned r = 0; r < m_projections.size(); r++ ) { if ( m_projections[r]->m_selected ) { TextureProjection * proj = m_projections[r]; double vec[4]; vec[0] = proj->m_pos[0] - point[0]; vec[1] = proj->m_pos[1] - point[1]; vec[2] = proj->m_pos[2] - point[2]; vec[3] = 1.0; m.apply( vec ); proj->m_pos[0] = vec[0] + point[0]; proj->m_pos[1] = vec[1] + point[1]; proj->m_pos[2] = vec[2] + point[2]; m.apply3( proj->m_upVec ); m.apply3( proj->m_seamVec ); applyProjection( r ); } } setupJoints(); invalidateNormals(); MU_RotateSelected * undo = new MU_RotateSelected(); undo->setMatrixPoint( m, point ); sendUndo( undo, true ); } } void Model::applyMatrix( const Matrix & m, OperationScopeE scope, bool animations, bool undoable ) { LOG_PROFILE(); m_changeBits |= MoveGeometry; bool global = (scope == OS_Global ); unsigned vcount = m_vertices.size(); unsigned bcount = m_joints.size(); unsigned pcount = m_points.size(); unsigned rcount = m_projections.size(); unsigned facount = m_frameAnims.size(); unsigned v; unsigned b; unsigned p; unsigned r; unsigned a; unsigned f; for ( v = 0; v < vcount; v++ ) { if ( global || m_vertices[ v ]->m_selected ) { m.apply3x( m_vertices[v]->m_coord ); } } Matrix * matArray = new Matrix[ bcount ]; for ( b = 0; b < bcount; b++ ) { matArray[b].loadIdentity(); matArray[b].setRotation( m_joints[b]->m_localRotation ); matArray[b].setTranslation( m_joints[b]->m_localTranslation ); Matrix inv; int p = m_joints[b]->m_parent; if ( p >= 0 && (global || parentJointSelected(p)) ) { // undo rotation and translation (keep scale) matArray[b] = matArray[b] * matArray[p]; inv = matArray[p]; inv.normalizeRotation(); inv = inv.getInverse(); } else { matArray[b] = matArray[b] * m; } Matrix rel = matArray[b] * inv; if ( global || parentJointSelected(b) ) { rel.normalizeRotation(); rel.getTranslation( m_joints[b]->m_localTranslation ); rel.getRotation( m_joints[b]->m_localRotation ); } } delete[] matArray; for ( p = 0; p < pcount; p++ ) { if ( global || m_points[ p ]->m_selected ) { Matrix pmat; pmat.setRotation( m_points[p]->m_rot ); pmat.setTranslation( m_points[p]->m_trans ); pmat = pmat * m; pmat.normalizeRotation(); pmat.getRotation( m_points[p]->m_rot ); pmat.getTranslation( m_points[p]->m_trans ); } } for ( r = 0; r < rcount; r++ ) { if ( global || m_projections[ r ]->m_selected ) { m.apply3x( m_projections[ r ]->m_pos ); m.apply3( m_projections[ r ]->m_upVec ); m.apply3( m_projections[ r ]->m_seamVec ); } } for ( a = 0; a < facount; a++ ) { unsigned fcount = m_frameAnims[a]->m_frameData.size(); for ( f = 0; f < fcount; f++ ) { for ( v = 0; v < vcount; v++ ) { if ( global || m_vertices[ v ]->m_selected ) { FrameAnimVertex * fav = (*m_frameAnims[a]->m_frameData[f]->m_frameVertices)[v]; m.apply3x( fav->m_coord ); } } for ( p = 0; p < pcount; p++ ) { if ( global || m_points[ p ]->m_selected ) { FrameAnimPoint * fap = (*m_frameAnims[a]->m_frameData[f]->m_framePoints)[p]; Matrix pmat; pmat.setRotation( fap->m_rot ); pmat.setTranslation( fap->m_trans ); pmat = pmat * m; pmat.getRotation( fap->m_rot ); pmat.getTranslation( fap->m_trans ); } } } } // Skeletal animations are handled by bone joint invalidateNormals(); setupJoints(); if ( undoable ) { MU_ApplyMatrix * undo = new MU_ApplyMatrix(); undo->setMatrix( m, scope, animations ); sendUndo( undo, true ); } else { clearUndo(); } } void Model::subdivideSelectedTriangles() { LOG_PROFILE(); if ( m_animationMode ) { return; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return; } sorted_list seList; vector verts; MU_SubdivideSelected * undo = new MU_SubdivideSelected(); sendUndo( undo ); unsigned vertexStart = m_vertices.size(); unsigned tlen = m_triangles.size(); for ( unsigned t = 0; t < tlen; t++ ) { if ( m_triangles[t]->m_selected ) { for ( unsigned v = 0; v < 3; v++ ) { unsigned a = m_triangles[t]->m_vertexIndices[ v ]; unsigned b = m_triangles[t]->m_vertexIndices[ (v+1) % 3 ]; unsigned index; if ( b < a ) { unsigned c = a; a = b; b = c; } SplitEdgesT e; e.a = a; e.b = b; int vNew = -1; if ( seList.find_sorted( e, index ) ) { vNew = seList[index].vNew; } else { double pa[3]; double pb[3]; getVertexCoords( a, pa ); getVertexCoords( b, pb ); // TODO this should really use addVertex() Vertex * vertex = Vertex::get(); vertex->m_coord[0] = (pa[0] + pb[0]) / 2; vertex->m_coord[1] = (pa[1] + pb[1]) / 2; vertex->m_coord[2] = (pa[2] + pb[2]) / 2; vertex->m_selected = true; vNew = m_vertices.size(); m_vertices.push_back( vertex ); e.vNew = vNew; seList.insert_sorted( e ); } verts.push_back( vNew ); } unsigned btri = m_triangles.size(); Triangle * tptr = Triangle::get(); tptr->m_selected = true; tptr->m_vertexIndices[0] = m_triangles[t]->m_vertexIndices[1]; tptr->m_vertexIndices[1] = verts[1]; tptr->m_vertexIndices[2] = verts[0]; m_triangles.push_back( tptr ); unsigned ctri = m_triangles.size(); tptr = Triangle::get(); tptr->m_selected = true; tptr->m_vertexIndices[0] = m_triangles[t]->m_vertexIndices[2]; tptr->m_vertexIndices[1] = verts[2]; tptr->m_vertexIndices[2] = verts[1]; m_triangles.push_back( tptr ); unsigned dtri = m_triangles.size(); tptr = Triangle::get(); tptr->m_selected = true; tptr->m_vertexIndices[0] = verts[0]; tptr->m_vertexIndices[1] = verts[1]; tptr->m_vertexIndices[2] = verts[2]; m_triangles.push_back( tptr ); m_triangles[t]->m_vertexIndices[1] = verts[0]; m_triangles[t]->m_vertexIndices[2] = verts[2]; MU_SubdivideTriangle * undo = new MU_SubdivideTriangle(); undo->subdivide( t, btri, ctri, dtri ); sendUndo( undo ); verts.clear(); } } invalidateNormals(); MU_SubdivideTriangle * vundo = new MU_SubdivideTriangle(); for ( unsigned i = vertexStart; i < m_vertices.size(); i++ ) { vundo->addVertex( i ); } sendUndo( vundo ); } void Model::unsubdivideTriangles( unsigned t1, unsigned t2, unsigned t3, unsigned t4 ) { LOG_PROFILE(); if ( m_animationMode ) { return; } m_triangles[t1]->m_vertexIndices[1] = m_triangles[t2]->m_vertexIndices[0]; m_triangles[t1]->m_vertexIndices[2] = m_triangles[t3]->m_vertexIndices[0]; Triangle * doomed; doomed = m_triangles[ t4 ]; removeTriangle( t4 ); doomed->release(); doomed = m_triangles[ t3 ]; removeTriangle( t3 ); doomed->release(); doomed = m_triangles[ t2 ]; removeTriangle( t2 ); doomed->release(); invalidateNormals(); } bool Model::setPointName( unsigned point, const char * name ) { if ( point < m_points.size() && name && name[0] ) { MU_SetPointName * undo = new MU_SetPointName(); undo->setName( point, name, m_points[point]->m_name.c_str() ); sendUndo( undo ); m_points[point]->m_name = name; return true; } else { return false; } } bool Model::setPointType( unsigned point, int type ) { if ( point < m_points.size() ) { /* // TODO: undo (if this is ever actually used) MU_SetPointName * undo = new MU_SetPointName(); undo->setName( point, name, m_points[point]->m_name.c_str() ); sendUndo( undo ); */ m_points[point]->m_type = type; return true; } else { return false; } } bool Model::setBoneJointName( unsigned joint, const char * name ) { if ( joint < m_joints.size() && name && name[0] ) { MU_SetJointName * undo = new MU_SetJointName(); undo->setName( joint, name, m_joints[joint]->m_name.c_str() ); sendUndo( undo ); m_joints[joint]->m_name = name; return true; } else { return false; } } bool Model::setBoneJointParent( unsigned joint, int parent ) { if ( joint < m_joints.size() && parent >= -1 ) { MU_SetJointParent * undo = new MU_SetJointParent(); undo->setJointParent( joint, parent, m_joints[joint]->m_parent ); sendUndo( undo ); m_joints[joint]->m_parent = parent; return true; } else { return false; } } bool Model::setBoneJointRotation( unsigned j, const double * rot ) { if ( j < m_joints.size() && rot ) { MU_SetJointRotation * undo = new MU_SetJointRotation(); undo->setJointRotation( j, rot, m_joints[j]->m_localRotation ); sendUndo(undo); for ( unsigned i = 0; i < 3; i++ ) { m_joints[j]->m_localRotation[i] = rot[i]; } return true; } return false; } bool Model::setBoneJointTranslation( unsigned j, const double * trans ) { if ( j < m_joints.size() && trans ) { MU_SetJointTranslation * undo = new MU_SetJointTranslation(); undo->setJointTranslation( j, trans, m_joints[j]->m_localTranslation ); sendUndo(undo); for ( unsigned i = 0; i < 3; i++ ) { m_joints[j]->m_localTranslation[i] = trans[i]; } return true; } return false; } void Model::operationComplete( const char * opname ) { if ( m_selecting ) { endSelectionDifference(); } m_undoMgr->operationComplete( opname ); updateObservers(); } void Model::forceAddOrDelete( bool o ) { if ( !o && m_forceAddOrDelete ) clearUndo(); m_forceAddOrDelete = o; } bool Model::setUndoEnabled( bool o ) { bool old = m_undoEnabled; m_undoEnabled = o; return old; } void Model::clearUndo() { m_undoMgr->clear(); } bool Model::canUndo() const { //if ( m_animationMode ) //{ // return m_animUndoMgr->canUndo(); //} //else { return m_undoMgr->canUndo(); } } bool Model::canRedo() const { //if ( m_animationMode ) //{ // return m_animUndoMgr->canRedo(); //} //else { return m_undoMgr->canRedo(); } } const char * Model::getUndoOpName() const { //if ( m_animationMode ) //{ // return m_animUndoMgr->getUndoOpName(); //} //else { return m_undoMgr->getUndoOpName(); } } const char * Model::getRedoOpName() const { //if ( m_animationMode ) //{ // return m_animUndoMgr->getRedoOpName(); //} //else { return m_undoMgr->getRedoOpName(); } } void Model::undo() { LOG_PROFILE(); //UndoList * list = (m_animationMode) ? m_animUndoMgr->undo() : m_undoMgr->undo(); UndoList * list = m_undoMgr->undo(); if ( list ) { log_debug( "got atomic undo list\n" ); setUndoEnabled( false ); // process back to front UndoList::reverse_iterator it; for ( it = list->rbegin(); it != list->rend(); it++ ) { ModelUndo * undo = static_cast( (*it) ); undo->undo( this ); } if ( !m_validJoints ) { setupJoints(); } setUndoEnabled( true ); updateObservers(); } m_selecting = false; } void Model::redo() { LOG_PROFILE(); //UndoList * list = (m_animationMode) ? m_animUndoMgr->redo() : m_undoMgr->redo(); UndoList * list = m_undoMgr->redo(); if ( list ) { log_debug( "got atomic redo list\n" ); setUndoEnabled( false ); // process front to back UndoList::iterator it; for ( it = list->begin(); it != list->end(); it++ ) { ModelUndo * undo = static_cast( (*it) ); undo->redo( this ); } if ( !m_validJoints ) { setupJoints(); } setUndoEnabled( true ); updateObservers(); } m_selecting = false; } void Model::undoCurrent() { LOG_PROFILE(); //UndoList * list = (m_animationMode) ? m_animUndoMgr->undoCurrent() : m_undoMgr->undoCurrent(); UndoList * list = m_undoMgr->undoCurrent(); if ( list ) { log_debug( "got atomic undo list\n" ); setUndoEnabled( false ); // process back to front UndoList::reverse_iterator it; for ( it = list->rbegin(); it != list->rend(); it++ ) { ModelUndo * undo = static_cast( (*it) ); undo->undo( this ); } if ( !m_validJoints ) { setupJoints(); } setUndoEnabled( true ); updateObservers(); } m_selecting = false; } bool Model::hideVertex( unsigned v ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( v < m_vertices.size() ) { m_vertices[ v ]->m_visible = false; return true; } else { return false; } } bool Model::hideTriangle( unsigned t ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( t < m_triangles.size() ) { m_triangles[ t ]->m_visible = false; return true; } else { return false; } } bool Model::hideJoint( unsigned j ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( j < m_joints.size() ) { m_joints[ j ]->m_visible = false; return true; } else { return false; } } bool Model::hidePoint( unsigned p ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( p < m_points.size() ) { m_points[ p ]->m_visible = false; return true; } else { return false; } } bool Model::unhideVertex( unsigned v ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( v < m_vertices.size() ) { m_vertices[ v ]->m_visible = true; return true; } else { return false; } } bool Model::unhideTriangle( unsigned t ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( t < m_triangles.size() ) { m_triangles[ t ]->m_visible = true; return true; } else { return false; } } bool Model::unhideJoint( unsigned j ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( j < m_joints.size() ) { m_joints[ j ]->m_visible = true; return true; } else { return false; } } bool Model::unhidePoint( unsigned p ) { LOG_PROFILE(); if ( m_animationMode ) { return false; } if ( p < m_points.size() ) { m_points[ p ]->m_visible = true; return true; } else { return false; } } bool Model::hideSelected() { LOG_PROFILE(); if ( m_animationMode ) { return false; } unsigned t = 0; unsigned v = 0; // Need to track whether we are hiding a vertex and any triangles attached to it, // or hiding a triangle, and only vertices if they are orphaned for ( v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->m_selected ) { m_vertices[v]->m_marked = true; } else { m_vertices[v]->m_marked = false; } } // Hide selected triangles for ( t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_selected ) { m_triangles[t]->m_visible = false; m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_marked = false; MU_Hide * undo = new MU_Hide( SelectTriangles ); undo->setHideDifference( t, m_triangles[t]->m_visible ); sendUndo( undo ); } } // Hide triangles with a lone vertex that is selected for ( t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_visible && ( m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_marked || m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_marked || m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_marked ) ) { m_triangles[t]->m_visible = false; MU_Hide * undo = new MU_Hide( SelectTriangles ); undo->setHideDifference( t, m_triangles[t]->m_visible ); sendUndo( undo ); } } // Find orphaned vertices for ( v = 0; v < m_vertices.size(); v++ ) { m_vertices[v]->m_marked = true; } for ( t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_visible ) { // Triangle is visible, vertices must be too m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_marked = false; } } // Hide selected vertices for ( v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->m_visible && m_vertices[v]->m_marked ) { m_vertices[v]->m_visible = false; MU_Hide * undo = new MU_Hide( SelectVertices ); undo->setHideDifference( v, m_vertices[v]->m_visible ); sendUndo( undo ); } } for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_selected ) { m_joints[j]->m_visible = false; MU_Hide * undo = new MU_Hide( SelectJoints ); undo->setHideDifference( j, m_joints[j]->m_visible ); sendUndo( undo ); } } for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_selected ) { m_points[p]->m_visible = false; MU_Hide * undo = new MU_Hide( SelectPoints ); undo->setHideDifference( p, m_points[p]->m_visible ); sendUndo( undo ); } } unselectAll(); return true; } bool Model::hideUnselected() { LOG_PROFILE(); if ( m_animationMode ) { return false; } unsigned t = 0; unsigned v = 0; // Need to track whether we are hiding a vertex and any triangles attached to it, // or hiding a triangle, and only vertices if they are orphaned // We could be doing both at the same for ( v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->m_selected ) { m_vertices[v]->m_marked = false; } else { m_vertices[v]->m_marked = true; } } // Hide triangles with any unselected vertices for ( t = 0; t < m_triangles.size(); t++ ) { if ( !m_triangles[t]->m_selected && ( !m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_selected || !m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_selected || !m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_selected ) ) { log_debug( "triangle %d is unselected, hiding\n", t ); m_triangles[t]->m_visible = false; m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_marked = false; MU_Hide * undo = new MU_Hide( SelectTriangles ); undo->setHideDifference( t, m_triangles[t]->m_visible ); sendUndo( undo ); } } // Find orphaned vertices for ( v = 0; v < m_vertices.size(); v++ ) { m_vertices[v]->m_marked = true; } for ( t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_visible ) { // Triangle is visible, vertices must be too m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_marked = false; m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_marked = false; } } // Hide selected vertices for ( v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->m_visible && m_vertices[v]->m_marked ) { log_debug( "vertex %d is visible and marked, hiding\n", v ); m_vertices[v]->m_visible = false; MU_Hide * undo = new MU_Hide( SelectVertices ); undo->setHideDifference( v, m_vertices[v]->m_visible ); sendUndo( undo ); } } for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_visible && !m_joints[j]->m_selected ) { m_joints[j]->m_visible = false; MU_Hide * undo = new MU_Hide( SelectJoints ); undo->setHideDifference( j, m_joints[j]->m_visible ); sendUndo( undo ); } } for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_visible && !m_points[p]->m_selected ) { m_points[p]->m_visible = false; MU_Hide * undo = new MU_Hide( SelectPoints ); undo->setHideDifference( p, m_points[p]->m_visible ); sendUndo( undo ); } } unselectAll(); return true; } bool Model::unhideAll() { LOG_PROFILE(); if ( m_animationMode ) { return false; } for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( !m_vertices[v]->m_visible ) { m_vertices[v]->m_visible = true; MU_Hide * undo = new MU_Hide( SelectVertices ); undo->setHideDifference( v, true ); sendUndo( undo ); } } for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( !m_triangles[t]->m_visible ) { m_triangles[t]->m_visible = true; MU_Hide * undo = new MU_Hide( SelectTriangles ); undo->setHideDifference( t, true ); sendUndo( undo ); } } for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( !m_joints[j]->m_visible ) { m_joints[j]->m_visible = true; MU_Hide * undo = new MU_Hide( SelectJoints ); undo->setHideDifference( j, true ); sendUndo( undo ); } } for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( !m_points[p]->m_visible ) { m_points[p]->m_visible = true; MU_Hide * undo = new MU_Hide( SelectPoints ); undo->setHideDifference( p, true ); sendUndo( undo ); } } return true; } void Model::hideTrianglesFromVertices() { LOG_PROFILE(); // Hide triangles with at least one vertex hidden for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( !m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_visible || !m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_visible || !m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_visible ) { m_triangles[t]->m_visible = false; } } } void Model::unhideTrianglesFromVertices() { LOG_PROFILE(); // Hide triangles with at least one vertex hidden for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_vertices[ m_triangles[t]->m_vertexIndices[0] ]->m_visible && m_vertices[ m_triangles[t]->m_vertexIndices[1] ]->m_visible && m_vertices[ m_triangles[t]->m_vertexIndices[2] ]->m_visible ) { m_triangles[t]->m_visible = true; } } } void Model::hideVerticesFromTriangles() { LOG_PROFILE(); // Hide vertices with all triangles hidden unsigned t; for ( t = 0; t < m_vertices.size(); t++ ) { m_vertices[t]->m_visible = false; } for ( t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_visible ) { for ( int v = 0; v < 3; v++ ) { m_vertices[ m_triangles[t]->m_vertexIndices[v] ]->m_visible = true; } } } } void Model::unhideVerticesFromTriangles() { LOG_PROFILE(); // Unhide vertices with at least one triangle visible for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_visible ) { for ( int v = 0; v < 3; v++ ) { m_vertices[ m_triangles[t]->m_vertexIndices[v] ]->m_visible = true; } } } } bool Model::getBoundingRegion( double *x1, double *y1, double *z1, double *x2, double *y2, double *z2 ) const { if ( x1 && y1 && z1 && x2 && y2 && z2 ) { int visible = 0; bool havePoint = false; *x1 = *y1 = *z1 = *x2 = *y2 = *z2 = 0.0; for ( unsigned v = 0; v < m_vertices.size(); v++ ) { if ( m_vertices[v]->m_visible ) { if ( havePoint ) { if ( m_vertices[v]->m_coord[0] < *x1 ) { *x1 = m_vertices[v]->m_coord[0]; } if ( m_vertices[v]->m_coord[0] > *x2 ) { *x2 = m_vertices[v]->m_coord[0]; } if ( m_vertices[v]->m_coord[1] < *y1 ) { *y1 = m_vertices[v]->m_coord[1]; } if ( m_vertices[v]->m_coord[1] > *y2 ) { *y2 = m_vertices[v]->m_coord[1]; } if ( m_vertices[v]->m_coord[2] < *z1 ) { *z1 = m_vertices[v]->m_coord[2]; } if ( m_vertices[v]->m_coord[2] > *z2 ) { *z2 = m_vertices[v]->m_coord[2]; } } else { *x1 = *x2 = m_vertices[v]->m_coord[0]; *y1 = *y2 = m_vertices[v]->m_coord[1]; *z1 = *z2 = m_vertices[v]->m_coord[2]; havePoint = true; } visible++; } } for ( unsigned j = 0; j < m_joints.size(); j++ ) { double coord[3]; m_joints[j]->m_absolute.getTranslation( coord ); if ( havePoint ) { if ( coord[0] < *x1 ) { *x1 = coord[0]; } if ( coord[0] > *x2 ) { *x2 = coord[0]; } if ( coord[1] < *y1 ) { *y1 = coord[1]; } if ( coord[1] > *y2 ) { *y2 = coord[1]; } if ( coord[2] < *z1 ) { *z1 = coord[2]; } if ( coord[2] > *z2 ) { *z2 = coord[2]; } } else { *x1 = *x2 = coord[0]; *y1 = *y2 = coord[1]; *z1 = *z2 = coord[2]; havePoint = true; } visible++; } for ( unsigned p = 0; p < m_points.size(); p++ ) { double coord[3]; coord[0] = m_points[p]->m_trans[0]; coord[1] = m_points[p]->m_trans[1]; coord[2] = m_points[p]->m_trans[2]; if ( havePoint ) { if ( coord[0] < *x1 ) { *x1 = coord[0]; } if ( coord[0] > *x2 ) { *x2 = coord[0]; } if ( coord[1] < *y1 ) { *y1 = coord[1]; } if ( coord[1] > *y2 ) { *y2 = coord[1]; } if ( coord[2] < *z1 ) { *z1 = coord[2]; } if ( coord[2] > *z2 ) { *z2 = coord[2]; } } else { *x1 = *x2 = coord[0]; *y1 = *y2 = coord[1]; *z1 = *z2 = coord[2]; havePoint = true; } visible++; } for ( unsigned p = 0; p < m_projections.size(); p++ ) { double coord[3]; double m = mag3(m_projections[p]->m_upVec); coord[0] = m_projections[p]->m_pos[0] + m; coord[1] = m_projections[p]->m_pos[1] + m; coord[2] = m_projections[p]->m_pos[2] + m; if ( havePoint ) { if ( coord[0] < *x1 ) { *x1 = coord[0]; } if ( coord[0] > *x2 ) { *x2 = coord[0]; } if ( coord[1] < *y1 ) { *y1 = coord[1]; } if ( coord[1] > *y2 ) { *y2 = coord[1]; } if ( coord[2] < *z1 ) { *z1 = coord[2]; } if ( coord[2] > *z2 ) { *z2 = coord[2]; } } else { *x1 = *x2 = coord[0]; *y1 = *y2 = coord[1]; *z1 = *z2 = coord[2]; havePoint = true; } coord[0] = m_projections[p]->m_pos[0] - m; coord[1] = m_projections[p]->m_pos[1] - m; coord[2] = m_projections[p]->m_pos[2] - m; if ( coord[0] < *x1 ) { *x1 = coord[0]; } if ( coord[0] > *x2 ) { *x2 = coord[0]; } if ( coord[1] < *y1 ) { *y1 = coord[1]; } if ( coord[1] > *y2 ) { *y2 = coord[1]; } if ( coord[2] < *z1 ) { *z1 = coord[2]; } if ( coord[2] > *z2 ) { *z2 = coord[2]; } visible++; } return ( visible != 0 ) ? true : false; } return false; } void Model::invertNormals( unsigned triangleNum ) { LOG_PROFILE(); if ( triangleNum < m_triangles.size() ) { int temp = m_triangles[ triangleNum ]->m_vertexIndices[0]; m_triangles[ triangleNum ]->m_vertexIndices[0] = m_triangles[ triangleNum ]->m_vertexIndices[2]; m_triangles[ triangleNum ]->m_vertexIndices[2] = temp; float texTemp = m_triangles[ triangleNum ]->m_s[0]; m_triangles[ triangleNum ]->m_s[0] = m_triangles[ triangleNum ]->m_s[2]; m_triangles[ triangleNum ]->m_s[2] = texTemp; texTemp = m_triangles[ triangleNum ]->m_t[0]; m_triangles[ triangleNum ]->m_t[0] = m_triangles[ triangleNum ]->m_t[2]; m_triangles[ triangleNum ]->m_t[2] = texTemp; invalidateNormals(); MU_InvertNormal * undo = new MU_InvertNormal(); undo->addTriangle( triangleNum ); sendUndo( undo ); } } bool Model::triangleFacesIn( unsigned triangleNum ) { if ( ! m_validNormals ) { calculateNormals(); } unsigned int tcount = m_triangles.size(); if ( triangleNum < tcount ) { int inFront = 0; int inBack = 0; int sideInFront = 0; int sideInBack = 0; double p1[3] = { 0, 0, 0 }; double p2[3] = { 0, 0, 0 }; Triangle * tri = m_triangles[ triangleNum ]; for ( int i = 0; i < 3; i++ ) { for ( int j = 0; j < 3; j++ ) { p1[i] += m_vertices[ tri->m_vertexIndices[j] ]->m_coord[i]; } p1[i] /= 3.0; } float norm[3] = { 0.0f, 0.0f, 0.0f }; getFlatNormal( triangleNum, norm ); p2[0] = norm[0] + p1[0]; p2[1] = norm[1] + p1[1]; p2[2] = norm[2] + p1[2]; for ( unsigned int t = 0; t < tcount; t++ ) { double tpoint[3][3]; double tnorm[3]; getVertexCoords( m_triangles[t]->m_vertexIndices[0], tpoint[0] ); getFlatNormal( t, norm ); tnorm[0] = norm[0]; tnorm[1] = norm[1]; tnorm[2] = norm[2]; if ( t != triangleNum ) { double ipoint[3] = { 0, 0, 0 }; int val = _findEdgePlaneIntersection( ipoint, p1, p2, tpoint[0], tnorm ); if ( val != 0 ) { getVertexCoords( m_triangles[t]->m_vertexIndices[1], tpoint[1] ); getVertexCoords( m_triangles[t]->m_vertexIndices[2], tpoint[2] ); int inTri = _pointInTriangle( ipoint, tpoint[0], tpoint[1], tpoint[2] ); if ( inTri >= 0 ) { if ( val > 0 ) { if ( inTri == 0 ) { sideInFront++; } else { inFront++; } } else { if ( inTri == 0 ) { sideInBack++; } else { inBack++; } } } } } } if ( (sideInFront & 1) == 0 ) { inFront += sideInFront / 2; } if ( (sideInBack & 1) == 0 ) { inBack += sideInBack / 2; } //log_debug( "front = %d back = %d\n", inFront, inBack ); return ((inFront & 1) != 0) && ((inBack & 1) == 0); } return false; } void Model::sendUndo( Undo * undo, bool listCombine ) { setSaved( false ); if ( m_undoEnabled ) { //if ( m_animationMode ) //{ // m_animUndoMgr->addUndo( undo ); //} //else { m_undoMgr->addUndo( undo, listCombine ); } } else { undo->undoRelease(); undo->release(); } } void Model::displayFrameAnimPrimitiveError() { model_status( this, StatusError, STATUSTIME_LONG, transll(QT_TRANSLATE_NOOP("LowLevel", "Cannot add or delete because you have frame animations. Try \"Merge...\" instead." )).c_str() ); } #endif // MM3D_EDIT int Model::addFormatData( FormatData * fd ) { m_changeBits |= AddOther; int n = -1; if ( fd ) { n = m_formatData.size(); m_formatData.push_back( fd ); } return n; } bool Model::deleteFormatData( unsigned index ) { vector< FormatData * >::iterator it; for ( it = m_formatData.begin(); it != m_formatData.end(); it++ ) { while ( index && it != m_formatData.end() ) { it++; index--; } if ( it != m_formatData.end() ) { delete (*it); m_formatData.erase( it ); return true; } } return false; } unsigned Model::getFormatDataCount() const { return m_formatData.size(); } Model::FormatData * Model::getFormatData( unsigned index ) const { if ( index < m_formatData.size() ) { return m_formatData[index]; } return NULL; } Model::FormatData * Model::getFormatDataByFormat( const char * format, unsigned index ) const { unsigned count = m_formatData.size(); for ( unsigned n = 0; n < count; n++ ) { FormatData * fd = m_formatData[n]; if ( strcasecmp( fd->format.c_str(), format ) == 0 && fd->index == index ) { return fd; } } return NULL; } int Model::getNumFrames() const { int count = 0; for ( unsigned anim = 0; anim < m_skelAnims.size(); anim++ ) { count += m_skelAnims[ anim ]->m_frameCount; } return count; } int Model::getBoneJointParent( unsigned j ) const { if ( j < m_joints.size() ) { return m_joints[j]->m_parent; } else { return -1; } } const char * Model::getBoneJointName( unsigned joint ) const { if ( joint < m_joints.size() ) { return m_joints[joint]->m_name.c_str(); } else { return NULL; } } const char * Model::getPointName( unsigned point ) const { if ( point < m_points.size() ) { return m_points[point]->m_name.c_str(); } else { return NULL; } } int Model::getPointByName( const char * name ) const { for ( unsigned int point = 0; point < m_points.size(); point++ ) { if ( strcmp( name, m_points[point]->m_name.c_str() ) == 0 ) { return point; } } return -1; } int Model::getPointType( unsigned point ) const { if ( point < m_points.size() ) { return m_points[point]->m_type; } else { return 0; } } int Model::getPointBoneJoint( unsigned p ) const { return getPrimaryPointInfluence( p ); } bool Model::getPositionCoords( const Position & pos, double *coord ) const { switch ( pos.type ) { case PT_Vertex: return getVertexCoords( pos.index, coord ); case PT_Joint: return getBoneJointCoords( pos.index, coord ); case PT_Point: return getPointCoords( pos.index, coord ); case PT_Projection: return getProjectionCoords( pos.index, coord ); default: log_error( "do not know how to get the position for position type %d\n", pos.type ); break; } return false; } bool Model::getVertexCoords( unsigned vertexNumber, double *coord ) const { switch ( m_animationMode ) { case ANIMMODE_NONE: if ( coord && vertexNumber < m_vertices.size() ) { for ( int t = 0; t < 3; t++ ) { coord[t] = m_vertices[ vertexNumber ]->m_coord[t]; } return true; } break; case ANIMMODE_FRAME: if ( coord && vertexNumber < m_vertices.size() ) { getFrameAnimVertexCoords( m_currentAnim, m_currentFrame, vertexNumber, coord[0], coord[1], coord[2] ); return true; } break; case ANIMMODE_SKELETAL: if ( coord ) { if ( vertexNumber < m_vertices.size() ) { Vertex * vertex = m_vertices[vertexNumber]; for ( int t = 0; t < 3; t++ ) { coord[t] = vertex->m_drawSource[t]; } } } break; default: break; } return false; } bool Model::getVertexCoordsUnanimated( unsigned vertexNumber, double *coord ) const { if ( coord && vertexNumber < m_vertices.size() ) { for ( int t = 0; t < 3; t++ ) { coord[t] = m_vertices[ vertexNumber ]->m_coord[t]; } return true; } return false; } bool Model::getVertexCoords2d( unsigned vertexNumber, ProjectionDirectionE dir, double *coord ) const { if ( coord && vertexNumber >= 0 && (unsigned) vertexNumber < m_vertices.size() ) { Vertex * vert = m_vertices[ vertexNumber ]; switch ( dir ) { case ViewFront: coord[0] = vert->m_coord[0]; coord[1] = vert->m_coord[1]; break; case ViewBack: coord[0] = -vert->m_coord[0]; coord[1] = vert->m_coord[1]; break; case ViewLeft: coord[0] = -vert->m_coord[2]; coord[1] = vert->m_coord[1]; break; case ViewRight: coord[0] = vert->m_coord[2]; coord[1] = vert->m_coord[1]; break; case ViewTop: coord[0] = vert->m_coord[0]; coord[1] = -vert->m_coord[2]; break; case ViewBottom: coord[0] = vert->m_coord[0]; coord[1] = vert->m_coord[2]; break; // Not an orthogonal view default: return false; break; } return true; } else { return false; } } int Model::getVertexBoneJoint( unsigned vertexNumber ) const { return getPrimaryVertexInfluence( vertexNumber ); } bool Model::getPointCoords( unsigned pointNumber, double *coord ) const { if ( coord && pointNumber < m_points.size() ) { int t; switch ( m_animationMode ) { case ANIMMODE_SKELETAL: { for ( t = 0; t < 3; t++ ) { coord[t] = m_points[ pointNumber ]->m_kfTrans[ t ]; } /* Matrix mat; Point * point = m_points[ pointNumber ]; mat.setTranslation( point->m_localTranslation ); mat.setRotation( point->m_localRotation ); int j = point->m_boneId; if ( j >= 0 ) { mat = mat * m_joints[j]->m_final; } for ( t = 0; t < 3; t++ ) { coord[t] = mat.get(3, t); } */ } break; case ANIMMODE_FRAME: getFrameAnimPointCoords( m_currentAnim, m_currentFrame, pointNumber, coord[0], coord[1], coord[2] ); break; case ANIMMODE_NONE: default: for ( t = 0; t < 3; t++ ) { coord[t] = m_points[ pointNumber ]->m_trans[ t ]; } break; } return true; } else { return false; } } bool Model::getPointOrientation( unsigned pointNumber, double * rot ) const { if ( rot && pointNumber < m_points.size() ) { int t; switch ( m_animationMode ) { case ANIMMODE_SKELETAL: { Matrix mat; Point * point = m_points[ pointNumber ]; mat.setTranslation( point->m_kfTrans ); mat.setRotation( point->m_kfRot ); mat.getRotation( rot ); /* Matrix mat; Point * point = m_points[ pointNumber ]; mat.setTranslation( point->m_localTranslation ); mat.setRotation( point->m_localRotation ); int j = point->m_boneId; if ( j >= 0 ) { mat = mat * m_joints[j]->m_final; } mat.getRotation( rot ); */ } break; case ANIMMODE_FRAME: getFrameAnimPointCoords( m_currentAnim, m_currentFrame, pointNumber, rot[0], rot[1], rot[2] ); break; case ANIMMODE_NONE: default: for ( t = 0; t < 3; t++ ) { rot[t] = m_points[ pointNumber ]->m_rot[ t ]; } break; } return true; } else { return false; } } bool Model::getPointRotation( unsigned pointNumber, double * rot ) const { if ( rot && pointNumber < m_points.size() ) { switch ( m_animationMode ) { case ANIMMODE_NONE: rot[0] = m_points[ pointNumber ]->m_rot[ 0 ]; rot[1] = m_points[ pointNumber ]->m_rot[ 1 ]; rot[2] = m_points[ pointNumber ]->m_rot[ 2 ]; return true; case ANIMMODE_FRAME: getFrameAnimPointRotation( m_currentAnim, m_currentFrame, pointNumber, rot[0], rot[1], rot[2] ); return true; default: break; } } return false; } bool Model::getPointTranslation( unsigned pointNumber, double * trans ) const { if ( trans && pointNumber < m_points.size() ) { trans[0] = m_points[ pointNumber ]->m_trans[ 0 ]; trans[1] = m_points[ pointNumber ]->m_trans[ 1 ]; trans[2] = m_points[ pointNumber ]->m_trans[ 2 ]; return true; } else { return false; } } bool Model::setPointRotation( unsigned pointNumber, const double * rot ) { if ( rot && pointNumber < m_points.size() ) { switch ( m_animationMode ) { case ANIMMODE_NONE: { Point * pnt = m_points[ pointNumber ]; MU_SetPointRotation * undo = new MU_SetPointRotation(); undo->setPointRotation( pointNumber, rot[0], rot[1], rot[2], pnt->m_rot[0], pnt->m_rot[1], pnt->m_rot[2] ); sendUndo( undo ); pnt->m_rot[ 0 ] = rot[ 0 ]; pnt->m_rot[ 1 ] = rot[ 1 ]; pnt->m_rot[ 2 ] = rot[ 2 ]; } return true; case ANIMMODE_FRAME: setFrameAnimPointRotation( m_currentAnim, m_currentFrame, pointNumber, rot[0], rot[1], rot[2] ); return true; default: break; } } return false; } bool Model::setPointTranslation( unsigned pointNumber, const double * trans ) { if ( trans && pointNumber < m_points.size() ) { Point * pnt = m_points[ pointNumber ]; MU_SetPointTranslation * undo = new MU_SetPointTranslation(); undo->setPointTranslation( pointNumber, trans[0], trans[1], trans[2], pnt->m_trans[0], pnt->m_trans[1], pnt->m_trans[2] ); sendUndo( undo ); pnt->m_trans[ 0 ] = trans[0]; pnt->m_trans[ 1 ] = trans[1]; pnt->m_trans[ 2 ] = trans[2]; return true; } else { return false; } } bool Model::getBoneJointCoords( unsigned jointNumber, double * coord ) const { if ( coord && jointNumber < m_joints.size() ) { if ( m_animationMode == ANIMMODE_SKELETAL ) { for ( int t = 0; t < 3; t++ ) { coord[t] = m_joints[ jointNumber ]->m_final.get(3, t); } } else { for ( int t = 0; t < 3; t++ ) { coord[t] = m_joints[ jointNumber ]->m_absolute.get(3, t); } } return true; } else { return false; } } bool Model::getBoneJointFinalMatrix( unsigned jointNumber, Matrix & m ) const { if ( jointNumber < m_joints.size() ) { m = m_joints[ jointNumber ]->m_final; return true; } else { return false; } } bool Model::getBoneJointAbsoluteMatrix( unsigned jointNumber, Matrix & m ) const { if ( jointNumber < m_joints.size() ) { m = m_joints[ jointNumber ]->m_absolute; return true; } else { return false; } } bool Model::getBoneJointRelativeMatrix( unsigned jointNumber, Matrix & m ) const { if ( jointNumber < m_joints.size() ) { m = m_joints[ jointNumber ]->m_relative; return true; } else { return false; } } bool Model::getPointFinalMatrix( unsigned pointNumber, Matrix & m ) const { if ( pointNumber < m_points.size() ) { Matrix mat; Point * p = m_points[ pointNumber ]; if ( m_animationMode == ANIMMODE_SKELETAL ) { /* mat.setTranslation( p->m_localTranslation ); mat.setRotation( p->m_localRotation ); if ( (unsigned) p->m_boneId < m_joints.size() ) { mat = mat * m_joints[ p->m_boneId ]->m_final; } else { mat = mat * m_localMatrix; } */ mat.setTranslation( p->m_kfTrans ); mat.setRotation( p->m_kfRot ); mat = mat * m_localMatrix; } else { mat.setTranslation( p->m_trans ); mat.setRotation( p->m_rot ); mat = mat * m_localMatrix; } m = mat; return true; } return false; } int Model::getTriangleVertex( unsigned triangleNumber, unsigned vertexIndex ) const { if ( triangleNumber < m_triangles.size() && vertexIndex < 3 ) { return m_triangles[ triangleNumber ]->m_vertexIndices[ vertexIndex ]; } else { return -1; } } bool Model::getNormal( unsigned triangleNum, unsigned vertexIndex, float *normal ) const { if ( triangleNum < m_triangles.size() && vertexIndex < 3 ) { for ( int t = 0; t < 3; t++ ) { normal[t] = m_triangles[ triangleNum ]->m_vertexNormals[vertexIndex][t]; } return true; } else { return false; } } bool Model::getFlatNormal( unsigned t, float *normal ) const { if ( t < m_triangles.size() ) { float x1 = m_vertices[m_triangles[t]->m_vertexIndices[0]]->m_coord[0]; float y1 = m_vertices[m_triangles[t]->m_vertexIndices[0]]->m_coord[1]; float z1 = m_vertices[m_triangles[t]->m_vertexIndices[0]]->m_coord[2]; float x2 = m_vertices[m_triangles[t]->m_vertexIndices[1]]->m_coord[0]; float y2 = m_vertices[m_triangles[t]->m_vertexIndices[1]]->m_coord[1]; float z2 = m_vertices[m_triangles[t]->m_vertexIndices[1]]->m_coord[2]; float x3 = m_vertices[m_triangles[t]->m_vertexIndices[2]]->m_coord[0]; float y3 = m_vertices[m_triangles[t]->m_vertexIndices[2]]->m_coord[1]; float z3 = m_vertices[m_triangles[t]->m_vertexIndices[2]]->m_coord[2]; float A = y1 * (z2 - z3) + y2 * (z3 - z1) + y3 * (z1 - z2); float B = z1 * (x2 - x3) + z2 * (x3 - x1) + z3 * (x1 - x2); float C = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2); // Get flat normal float len = sqrt((A * A) + (B * B) + (C * C)); A = A / len; B = B / len; C = C / len; normal[0] = A; normal[1] = B; normal[2] = C; return true; } else { return false; } } float Model::cosToPoint( unsigned t, double * point ) const { if ( t < m_triangles.size() ) { float x1 = m_vertices[m_triangles[t]->m_vertexIndices[0]]->m_coord[0]; float y1 = m_vertices[m_triangles[t]->m_vertexIndices[0]]->m_coord[1]; float z1 = m_vertices[m_triangles[t]->m_vertexIndices[0]]->m_coord[2]; float x2 = m_vertices[m_triangles[t]->m_vertexIndices[1]]->m_coord[0]; float y2 = m_vertices[m_triangles[t]->m_vertexIndices[1]]->m_coord[1]; float z2 = m_vertices[m_triangles[t]->m_vertexIndices[1]]->m_coord[2]; float x3 = m_vertices[m_triangles[t]->m_vertexIndices[2]]->m_coord[0]; float y3 = m_vertices[m_triangles[t]->m_vertexIndices[2]]->m_coord[1]; float z3 = m_vertices[m_triangles[t]->m_vertexIndices[2]]->m_coord[2]; float A = y1 * (z2 - z3) + y2 * (z3 - z1) + y3 * (z1 - z2); float B = z1 * (x2 - x3) + z2 * (x3 - x1) + z3 * (x1 - x2); float C = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2); // Get flat normal float len = sqrt((A * A) + (B * B) + (C * C)); A = A / len; B = B / len; C = C / len; float normal[3]; normal[0] = A; normal[1] = B; normal[2] = C; float vec[3]; vec[0] = point[0] - x1; vec[1] = point[1] - y1; vec[2] = point[2] - z1; // normalized vector from plane to point normalize3( vec ); float f = dot3( normal, vec ); log_debug( " dot3( %f,%f,%f %f,%f,%f )\n", normal[0], normal[1], normal[2], vec[0], vec[1], vec[2] ); log_debug( " behind triangle dot check is %f\n", f ); return f; } else { return 0.0f; } } bool Model::getBoneVector( unsigned joint, double * vec, const double * coord ) const { if ( joint >= m_joints.size() ) { return false; } double jcoord[3] = { 0, 0, 0 }; getBoneJointCoords( joint, jcoord ); double cdist = 0.0; int child = -1; int bcount = m_joints.size(); // find best child bone joint vector based on the min distance between // the target coordinate and the child bone joint coordinate for ( int b = 0; b < bcount; b++ ) { if ( getBoneJointParent( b ) == (int) joint ) { double ccoord[3]; getBoneJointCoords( b, ccoord ); double d = distance( ccoord, coord ); if ( child < 0 || d < cdist ) { child = b; cdist = d; vec[0] = ccoord[0] - jcoord[0]; vec[1] = ccoord[1] - jcoord[1]; vec[2] = ccoord[2] - jcoord[2]; } } } if ( child < 0 ) { int parent = getBoneJointParent( joint ); if ( parent < 0 ) { // no children, no parent // return max influence return false; } getBoneJointCoords( parent, vec ); cdist = distance( vec, coord ); // We're using the parent instead of the child, so invert the direction vec[0] = jcoord[0] - vec[0]; vec[1] = jcoord[1] - vec[1]; vec[2] = jcoord[2] - vec[2]; } normalize3( vec ); return true; } void Model::calculateNormals() { LOG_PROFILE(); vector< vector > acl_normmap; acl_normmap.resize( m_vertices.size() ); // accumulate normals std::vector::iterator tri_it; for ( tri_it = m_triangles.begin(); tri_it != m_triangles.end(); ++tri_it ) { Triangle * tri = *tri_it; tri->m_marked = false; float x1 = m_vertices[tri->m_vertexIndices[0]]->m_coord[0]; float y1 = m_vertices[tri->m_vertexIndices[0]]->m_coord[1]; float z1 = m_vertices[tri->m_vertexIndices[0]]->m_coord[2]; float x2 = m_vertices[tri->m_vertexIndices[1]]->m_coord[0]; float y2 = m_vertices[tri->m_vertexIndices[1]]->m_coord[1]; float z2 = m_vertices[tri->m_vertexIndices[1]]->m_coord[2]; float x3 = m_vertices[tri->m_vertexIndices[2]]->m_coord[0]; float y3 = m_vertices[tri->m_vertexIndices[2]]->m_coord[1]; float z3 = m_vertices[tri->m_vertexIndices[2]]->m_coord[2]; float A = y1 * (z2 - z3) + y2 * (z3 - z1) + y3 * (z1 - z2); float B = z1 * (x2 - x3) + z2 * (x3 - x1) + z3 * (x1 - x2); float C = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2); // Get flat normal float len = sqrt((A * A) + (B * B) + (C * C)); A = A / len; B = B / len; C = C / len; tri->m_flatNormals[0] = A; tri->m_flatNormals[1] = B; tri->m_flatNormals[2] = C; // Accumulate for smooth normal, weighted by face angle for ( int vert = 0; vert < 3; vert++ ) { unsigned index = tri->m_vertexIndices[vert]; vector< NormAngleAccum > & acl = acl_normmap[index]; float ax = 0.0f; float ay = 0.0f; float az = 0.0f; float bx = 0.0f; float by = 0.0f; float bz = 0.0f; switch ( vert ) { case 0: { ax = x2 - x1; ay = y2 - y1; az = z2 - z1; bx = x3 - x1; by = y3 - y1; bz = z3 - z1; } break; case 1: ax = x1 - x2; ay = y1 - y2; az = z1 - z2; bx = x3 - x2; by = y3 - y2; bz = z3 - z2; break; case 2: ax = x1 - x3; ay = y1 - y3; az = z1 - z3; bx = x2 - x3; by = y2 - y3; bz = z2 - z3; break; default: break; } float ad = sqrt( ax*ax + ay*ay + az*az ); float bd = sqrt( bx*bx + by*by + bz*bz ); NormAngleAccum aacc; aacc.norm[0] = A; aacc.norm[1] = B; aacc.norm[2] = C; aacc.angle = fabs( acos( (ax*bx + ay*by + az*bz) / (ad * bd) ) ); acl.push_back( aacc ); } } // Apply accumulated normals to triangles for ( unsigned g = 0; g < m_groups.size(); g++ ) { Group * grp = m_groups[g]; float maxAngle = grp->m_angle; if ( maxAngle < 0.50f ) { maxAngle = 0.50f; } maxAngle *= PIOVER180; for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { Triangle * tri = m_triangles[*it]; tri->m_marked = true; for ( int vert = 0; vert < 3; vert++ ) { unsigned v = tri->m_vertexIndices[vert]; { vector< NormAngleAccum > & acl = acl_normmap[v]; float A = 0.0f; float B = 0.0f; float C = 0.0f; unsigned count = acl.size(); unsigned n; // Use const_iterator instead? for ( n = 0; n < count; n++ ) { float crossprod = tri->m_flatNormals[0] * acl[n].norm[0] + tri->m_flatNormals[1] * acl[n].norm[1] + tri->m_flatNormals[2] * acl[n].norm[2]; // Don't allow it to go over 1.0f float angle = 0.0f; if ( crossprod < 0.99999f ) { angle = fabs( acos( crossprod ) ); } if ( angle <= maxAngle ) { A += acl[n].norm[0]; B += acl[n].norm[1]; C += acl[n].norm[2]; } } float len = sqrt( A*A + B*B + C*C ); if ( len >= 0.0001f ) { tri->m_vertexNormals[vert][0] = A / len; tri->m_vertexNormals[vert][1] = B / len; tri->m_vertexNormals[vert][2] = C / len; } else { tri->m_vertexNormals[vert][0] = tri->m_flatNormals[0]; tri->m_vertexNormals[vert][1] = tri->m_flatNormals[1]; tri->m_vertexNormals[vert][2] = tri->m_flatNormals[2]; } } } } } for ( tri_it = m_triangles.begin(); tri_it != m_triangles.end(); ++tri_it ) { Triangle * tri = *tri_it; if ( !tri->m_marked ) { for ( int vert = 0; vert < 3; vert++ ) { unsigned v = tri->m_vertexIndices[vert]; { vector< NormAngleAccum > & acl = acl_normmap[v]; float A = 0.0f; float B = 0.0f; float C = 0.0f; unsigned count = acl.size(); unsigned n; for ( n = 0; n < count; n++ ) { float crossprod = tri->m_flatNormals[0] * acl[n].norm[0] + tri->m_flatNormals[1] * acl[n].norm[1] + tri->m_flatNormals[2] * acl[n].norm[2]; // Don't allow it to go over 1.0f float angle = 0.0f; if ( crossprod < 0.99999f ) { angle = fabs( acos( crossprod ) ); } if ( angle <= 45.0f * PIOVER180 ) { A += acl[n].norm[0]; B += acl[n].norm[1]; C += acl[n].norm[2]; } } float len = sqrt( A*A + B*B + C*C ); NormAccum acc; acc.norm[0] = A / len; acc.norm[1] = B / len; acc.norm[2] = C / len; tri->m_vertexNormals[vert][0] = acc.norm[0]; tri->m_vertexNormals[vert][1] = acc.norm[1]; tri->m_vertexNormals[vert][2] = acc.norm[2]; } } } tri->m_marked = false; } for ( unsigned m = 0; m < m_groups.size(); m++ ) { Group * grp = m_groups[m]; double percent = (double) grp->m_smooth / 255.0; for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { Triangle * tri = m_triangles[ *it ]; for ( int v = 0; v < 3; v++ ) { if ( grp->m_smooth > 0 ) { for ( unsigned i = 0; i < 3; i++ ) { tri->m_finalNormals[v][i] = tri->m_flatNormals[i] + ( tri->m_vertexNormals[v][i] - tri->m_flatNormals[i] ) * percent; } normalize3( tri->m_finalNormals[v] ); } else { tri->m_finalNormals[v][0] = tri->m_flatNormals[0]; tri->m_finalNormals[v][1] = tri->m_flatNormals[1]; tri->m_finalNormals[v][2] = tri->m_flatNormals[2]; } } } } m_validNormals = true; m_validBspTree = false; } void Model::calculateSkelNormals() { LOG_PROFILE(); log_debug( "calculateSkelNormals()\n" ); if ( ! m_validNormals ) { calculateNormals(); } } void Model::calculateFrameNormals( unsigned anim ) { LOG_PROFILE(); if ( ! m_validNormals ) { calculateNormals(); } if ( anim < m_frameAnims.size() ) { FrameAnim * fa = m_frameAnims[ anim ]; for ( unsigned frame = 0; frame < fa->m_frameData.size(); frame++ ) { FrameAnimVertexList & favl = *fa->m_frameData[frame]->m_frameVertices; for ( unsigned v = 0; v < m_vertices.size(); v++ ) { favl[v]->m_normal[0] = 0.0f; favl[v]->m_normal[1] = 0.0f; favl[v]->m_normal[2] = 0.0f; } // accumulate normals for ( unsigned t = 0; t < m_triangles.size(); t++ ) { Triangle * tri = m_triangles[t]; float x1 = favl[tri->m_vertexIndices[0]]->m_coord[0]; float y1 = favl[tri->m_vertexIndices[0]]->m_coord[1]; float z1 = favl[tri->m_vertexIndices[0]]->m_coord[2]; float x2 = favl[tri->m_vertexIndices[1]]->m_coord[0]; float y2 = favl[tri->m_vertexIndices[1]]->m_coord[1]; float z2 = favl[tri->m_vertexIndices[1]]->m_coord[2]; float x3 = favl[tri->m_vertexIndices[2]]->m_coord[0]; float y3 = favl[tri->m_vertexIndices[2]]->m_coord[1]; float z3 = favl[tri->m_vertexIndices[2]]->m_coord[2]; float A = y1 * (z2 - z3) + y2 * (z3 - z1) + y3 * (z1 - z2); float B = z1 * (x2 - x3) + z2 * (x3 - x1) + z3 * (x1 - x2); float C = x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2); // Get flat normal float len = sqrt((A * A) + (B * B) + (C * C)); A = A / len; B = B / len; C = C / len; // Accumulate for smooth normal for ( int vert = 0; vert < 3; vert++ ) { unsigned v = tri->m_vertexIndices[vert]; favl[v]->m_normal[0] += A; favl[v]->m_normal[1] += B; favl[v]->m_normal[2] += C; } } // Normalize the accumulated normals for ( unsigned v = 0; v < m_vertices.size(); v++ ) { normalize3(favl[v]->m_normal); } fa->m_validNormals = true; } } } void Model::invalidateNormals() { m_changeBits |= MoveGeometry; if ( m_validNormals ) { unsigned anim; for ( anim = 0; anim < m_skelAnims.size(); anim++ ) { m_skelAnims[anim]->m_validNormals = false; } for ( anim = 0; anim < m_frameAnims.size(); anim++ ) { m_frameAnims[anim]->m_validNormals = false; } m_validNormals = false; } m_validBspTree = false; } void Model::calculateBspTree() { log_debug( "calculating BSP tree\n" ); m_bspTree.clear(); for ( unsigned m = 0; m < m_groups.size(); m++ ) { Group * grp = m_groups[m]; if ( grp->m_materialIndex >= 0 ) { int index = grp->m_materialIndex; Texture * tex = m_materials[index]->m_textureData; if ( tex && tex->m_format == Texture::FORMAT_RGBA ) { for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { Triangle * triangle = m_triangles[ *it ]; triangle->m_marked = true; if ( triangle->m_visible ) { BspTree::Poly * poly = BspTree::Poly::get(); for (int i = 0; i < 3; i++ ) { poly->coord[0][i] = m_vertices[ triangle->m_vertexIndices[0] ]->m_coord[i]; poly->coord[1][i] = m_vertices[ triangle->m_vertexIndices[1] ]->m_coord[i]; poly->coord[2][i] = m_vertices[ triangle->m_vertexIndices[2] ]->m_coord[i]; poly->s[i] = triangle->m_s[i]; poly->t[i] = triangle->m_t[i]; poly->drawNormals[0][i] = triangle->m_finalNormals[0][i]; poly->drawNormals[1][i] = triangle->m_finalNormals[1][i]; poly->drawNormals[2][i] = triangle->m_finalNormals[2][i]; poly->norm[i] = triangle->m_flatNormals[i]; } poly->texture = index; poly->material = static_cast< void *>( m_materials[ index ] ); poly->calculateD(); m_bspTree.addPoly( poly ); } } } } } m_validBspTree = true; } void Model::invalidateBspTree() { m_validBspTree = false; } bool Model::isTriangleMarked( unsigned int t ) const { if ( t < m_triangles.size() ) { return m_triangles[t]->m_userMarked; } return false; } void Model::setTriangleMarked( unsigned t, bool marked ) { if ( t < m_triangles.size() ) { m_triangles[t]->m_userMarked = marked; } } void Model::clearMarkedTriangles() { unsigned tcount = m_triangles.size(); for ( unsigned t = 0; t < tcount; t++ ) { m_triangles[t]->m_userMarked = false; } } void model_show_alloc_stats() { log_debug( "\n" ); log_debug( "primitive allocation stats (recycler/total)\n" ); log_debug( "Model: none/%d\n", _allocated ); Model::Vertex::stats(); Model::Triangle::stats(); Model::Group::stats(); Model::Material::stats(); Model::Keyframe::stats(); Model::Joint::stats(); Model::Point::stats(); Model::TextureProjection::stats(); Model::SkelAnim::stats(); Model::FrameAnim::stats(); Model::FrameAnimVertex::stats(); Model::FrameAnimPoint::stats(); BspTree::Poly::stats(); BspTree::Node::stats(); log_debug( "Textures: none/%d\n", Texture::s_allocated ); log_debug( "GlTextures: none/%d\n", Model::s_glTextures ); #ifdef MM3D_EDIT log_debug( "ModelUndo: none/%d\n", ModelUndo::s_allocated ); #endif // MM3D_EDIT log_debug( "\n" ); } int model_free_primitives() { int c = 0; log_debug( "purging primitive recycling lists\n" ); c += Model::Vertex::flush(); c += Model::Triangle::flush(); c += Model::Group::flush(); c += Model::Material::flush(); c += Model::Joint::flush(); c += Model::Point::flush(); c += Model::Keyframe::flush(); c += Model::SkelAnim::flush(); c += BspTree::Poly::flush(); c += BspTree::Node::flush(); c += Model::FrameAnim::flush(); c += Model::FrameAnimVertex::flush(); c += Model::FrameAnimPoint::flush(); return c; } mm3d-1.3.7/src/libmm3d/pcxtex.cc0000644000175000017500000003305610744511346013257 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ // This file was heavily modified from the gimp PCX plugin. // //------------------------------------------------------------------ // Original header comments follow: // /* pcx.c GIMP plug-in for loading & saving PCX files */ /* This code is based in parts on code by Francisco Bustamante, but the largest portion of the code has been rewritten and is now maintained occasionally by Nick Lamb njl195@zepler.org.uk */ /* New for 1998 -- Load 1, 4, 8 & 24 bit PCX files */ /* -- Save 8 & 24 bit PCX files */ /* 1998-01-19 - fixed some endianness problems (Raphael Quinet) */ /* 1998-02-05 - merged patch with "official" tree, some tidying up (njl) */ /* 1998-05-17 - changed email address, more tidying up (njl) */ /* 1998-05-31 - //log_error (njl) */ /* Please contact me if you can't use your PCXs with this tool, I want The GIMP to have the best file filters on the planet */ // // End original comments for gimp PCX plugin //------------------------------------------------------------------ // #include "pcxtex.h" #include "mm3dconfig.h" #include "endianconfig.h" #include "log.h" #include #include #include #include using std::list; using std::string; PcxTextureFilter::PcxTextureFilter() : m_texture( NULL ) { } PcxTextureFilter::~PcxTextureFilter() { } Texture::ErrorE PcxTextureFilter::readFile( Texture * texture, const char * filename ) { if ( texture && filename ) { m_texture = texture; Texture::ErrorE rval = load_image( filename ); m_texture = NULL; texture->m_format = Texture::FORMAT_RGB; texture->m_filename = strdup( filename ); const char * name = strrchr( filename, DIR_SLASH ); if ( name ) { texture->m_name = strdup( &name[1] ); } else { texture->m_name = strdup( filename ); } char * ext = strrchr( texture->m_name, '.' ); if ( ext ) { ext[0] = '\0'; } return rval; } else { return Texture::ERROR_BAD_ARGUMENT; } } static uint8_t _mono[6]= { 0, 0, 0, 255, 255, 255 }; static struct { uint8_t manufacturer; uint8_t version; uint8_t compression; uint8_t bpp; int16_t x1, y1; int16_t x2, y2; int16_t hdpi; int16_t vdpi; uint8_t colormap[48]; uint8_t reserved; uint8_t planes; int16_t bytesperline; int16_t color; uint8_t filler[58]; } pcx_header; Texture::ErrorE PcxTextureFilter::load_image ( const char * filename ) { FILE *fd; int offset_x, offset_y; fd = fopen (filename, "rb"); if (!fd) { return Texture::ERROR_NO_FILE; } read( pcx_header.manufacturer, fd ); read( pcx_header.version, fd ); read( pcx_header.compression, fd ); read( pcx_header.bpp, fd ); read( pcx_header.x1, fd ); read( pcx_header.y1, fd ); read( pcx_header.x2, fd ); read( pcx_header.y2, fd ); read( pcx_header.hdpi, fd ); read( pcx_header.vdpi, fd ); readBytes( pcx_header.colormap, sizeof(pcx_header.colormap), fd ); read( pcx_header.reserved, fd ); read( pcx_header.planes, fd ); read( pcx_header.bytesperline, fd ); read( pcx_header.color, fd ); readBytes( pcx_header.filler, sizeof(pcx_header.filler), fd ); if ( ftell(fd) != 128 ) { fclose( fd ); return Texture::ERROR_BAD_MAGIC; } if (pcx_header.manufacturer != 10) { fclose( fd ); return Texture::ERROR_BAD_MAGIC; } offset_x = (pcx_header.x1); offset_y = (pcx_header.y1); m_texture->m_width = (pcx_header.x2) - offset_x + 1; m_texture->m_height = (pcx_header.y2) - offset_y + 1; m_texture->m_data = new uint8_t[ m_texture->m_width * m_texture->m_height * 3 ]; if (pcx_header.planes == 1 && pcx_header.bpp == 1) { memcpy( m_palette, _mono, (2*3) ); load_1 (fd, m_texture->m_width, m_texture->m_height, m_texture->m_data, (pcx_header.bytesperline)); } else if (pcx_header.planes == 4 && pcx_header.bpp == 1) { memcpy( m_palette, pcx_header.colormap, (16*3) ); load_4(fd, m_texture->m_width, m_texture->m_height, m_texture->m_data, (pcx_header.bytesperline)); } else if (pcx_header.planes == 1 && pcx_header.bpp == 8) { int pos = ftell( fd ); fseek(fd, -(256*3), SEEK_END); fread(m_palette, (256*3), sizeof(uint8_t), fd); fseek( fd, pos, SEEK_SET ); load_8(fd, m_texture->m_width, m_texture->m_height, m_texture->m_data, (pcx_header.bytesperline)); } else if (pcx_header.planes == 3 && pcx_header.bpp == 8) { load_24(fd, m_texture->m_width, m_texture->m_height, m_texture->m_data, (pcx_header.bytesperline)); } else { fclose( fd ); return Texture::ERROR_UNSUPPORTED_VERSION; } fclose( fd ); return Texture::ERROR_NONE; } bool PcxTextureFilter::canRead( const char * filename ) { if ( filename == NULL ) { return false; } unsigned len = strlen( filename ); if ( strcasecmp( &filename[len-4], ".pcx" ) == 0 ) { return true; } return false; } list PcxTextureFilter::getReadTypes() { list rval; rval.push_back( "*.PCX" ); return rval; } list PcxTextureFilter::getWriteTypes() { list rval; //rval.push_back( "*.PCX" ); return rval; } void PcxTextureFilter::load_8 (FILE *fp, int m_width, int m_height, uint8_t *buffer, int bytes) { int x, y; uint8_t *line; line = (uint8_t *) malloc (bytes); uint8_t * row; for (y = m_height - 1; y >= 0; --y) { row = &buffer[ y * (m_width*3) ]; readline (fp, line, bytes); for (x = 0; x < m_width; ++x) { memcpy( &row[x*3], m_palette[ line[x] ], 3 ); } } free (line); } void PcxTextureFilter::load_24 (FILE *fp, int m_width, int m_height, uint8_t *buffer, int bytes) { int x, y, c; uint8_t * line; line = (uint8_t *) malloc (bytes * 3); uint8_t * row; for (y = m_height - 1; y >= 0; --y) { row = &buffer[ y * (m_width*3) ]; for (c = 0; c < 3; ++c) { readline (fp, line, bytes); for (x = 0; x < m_width; ++x) { row[x * 3 + c] = line[x]; } } } free (line); } void PcxTextureFilter::load_1 (FILE *fp, int m_width, int m_height, uint8_t *buffer, int bytes) { int x, y; uint8_t *line; line = (uint8_t *) malloc (bytes); uint8_t * row; for (y = m_height - 1; y >= 0; --y) { row = &buffer[ y * (m_width*3) ]; readline (fp, line, bytes); for (x = 0; x < m_width; ++x) { if (line[x / 8] & (128 >> (x % 8))) { memcpy( &row[x*3], m_palette[ 1 ], 3 ); } else { memcpy( &row[x*3], m_palette[ 0 ], 3 ); } } } free (line); } void PcxTextureFilter::load_4 (FILE *fp, int m_width, int m_height, uint8_t *buffer, int bytes) { // TODO implement this if I ever want it to work /* int x, y, c; uint8_t *line; line= (uint8_t *) malloc (bytes); uint8_t * row; for (y = m_height - 1; y >= 0; --y) { row = &buffer[ y * (m_width*3) ]; for (x = 0; x < m_width; ++x) row[x] = 0; for (c = 0; c < 4; ++c) { readline(fp, line, bytes); for (x = 0; x < m_width; ++x) { if (line[x / 8] & (128 >> (x % 8))) buffer[x] += (1 << c); } } } free (line); */ } void PcxTextureFilter::readline (FILE *fp, uint8_t *buffer, int bytes) { static uint8_t count = 0, value = 0; if (pcx_header.compression) { while (bytes--) { if (count == 0) { value = fgetc (fp); if (value < 0xc0) { count = 1; } else { count = value - 0xc0; value = fgetc (fp); } } count--; *(buffer++) = value; } } else { fread (buffer, bytes, 1, fp); } } void PcxTextureFilter::read( uint8_t & val, FILE * fp ) { fread( &val, sizeof(val), 1, fp ); } void PcxTextureFilter::read( int16_t & val, FILE * fp ) { fread( &val, sizeof(val), 1, fp ); val = ltoh_16( val ); } void PcxTextureFilter::readBytes( void * buf, size_t len, FILE * fp ) { fread( buf, len, 1, fp ); } /* bool save_image (char *filename, int32_t image, int32_t layer) { FILE *fp; uint8_t *cmap= 0, *pixels; int offset_x, offset_y, m_width, m_height; int colors, i; //m_width = drawable->m_width; //m_height = drawable->m_height; pcx_header.manufacturer = 0x0a; pcx_header.version = 5; pcx_header.compression = 1; uint32_t drawable_type = 0; switch (drawable_type) { case 0: // GIMP_INDEXED_IMAGE: pcx_header.bpp = 8; pcx_header.bytesperline = (m_width); pcx_header.planes = 1; pcx_header.color = (1); break; case 1: // GIMP_RGB_IMAGE: pcx_header.bpp = 8; pcx_header.planes = 3; pcx_header.color = (1); pcx_header.bytesperline = (m_width); break; case 2: // GIMP_GRAY_IMAGE: pcx_header.bpp = 8; pcx_header.planes = 1; pcx_header.color = (2); pcx_header.bytesperline = (m_width); break; default: //log_error ("PCX Can't save this image type\nFlatten your image\n"); return false; break; } if ((fp = fopen(filename, "wb")) == NULL) { //log_error ("PCX Can't open \n%s", filename); return false; } pixels = (uint8_t *) malloc (m_width * m_height * pcx_header.planes); pcx_header.x1 = (offset_x); pcx_header.y1 = (offset_y); pcx_header.x2 = (offset_x + m_width - 1); pcx_header.y2 = (offset_y + m_height - 1); pcx_header.hdpi = (300); pcx_header.vdpi = (300); pcx_header.reserved = 0; fwrite (&pcx_header, 128, 1, fp); switch (drawable_type) { case 0: // GIMP_INDEXED_IMAGE: save_8 (fp, m_width, m_height, pixels); fputc (0x0c, fp); fwrite (cmap, colors, 3, fp); for (i = colors; i < 256; i++) { fputc (0, fp); fputc (0, fp); fputc (0, fp); } break; case 1: // GIMP_RGB_IMAGE: save_24 (fp, m_width, m_height, pixels); break; case 2: // GIMP_GRAY_IMAGE: save_8 (fp, m_width, m_height, pixels); fputc (0x0c, fp); for (i = 0; i < 256; i++) { fputc ((uint8_t) i, fp); fputc ((uint8_t) i, fp); fputc ((uint8_t) i, fp); } break; default: //log_error ("Can't save this image as PCX\nFlatten your image\n"); return false; break; } free (pixels); fclose (fp); return true; } static void save_8 (FILE *fp, int m_width, int m_height, uint8_t *buffer) { int row; for (row = 0; row < m_height; ++row) { writeline (fp, buffer, m_width); buffer += m_width; } } static void save_24 (FILE *fp, int m_width, int m_height, uint8_t *buffer) { int x, y, c; uint8_t *line; line = (uint8_t *) malloc (m_width); for (y = 0; y < m_height; ++y) { for (c = 0; c < 3; ++c) { for (x = 0; x < m_width; ++x) { line[x] = buffer[(3*x) + c]; } writeline (fp, line, m_width); } buffer += m_width * 3; } free (line); } static void writeline (FILE *fp, uint8_t *buffer, int bytes) { uint8_t value, count; uint8_t *finish = buffer+ bytes; while (buffer < finish) { value = *(buffer++); count = 1; while (buffer < finish && count < 63 && *buffer == value) { count++; buffer++; } if (value < 0xc0 && count == 1) { fputc (value, fp); } else { fputc (0xc0 + count, fp); fputc (value, fp); } } } */ #ifdef PLUGIN static PcxTextureFilter * s_filter = NULL; //------------------------------------------------------------------ // Plugin functions //------------------------------------------------------------------ extern "C" bool plugin_init() { if ( s_filter == NULL ) { s_filter = new PcxTextureFilter(); TextureManager * texmgr = TextureManager::getInstance(); texmgr->registerTextureFilter( s_filter ); } log_debug( "PCX texture filture plugin initialized\n" ); return true; } extern "C" bool plugin_uninit() { s_filter = NULL; // TextureManager deletes filters log_debug( "PCX texture filture plugin uninitialized\n" ); return true; } extern "C" const char * plugin_version() { return "1.0.0"; } extern "C" const char * plugin_desc() { return "PCX texture filture"; } #endif // PLUGIN mm3d-1.3.7/src/libmm3d/memdatadest.h0000644000175000017500000000346310754751776014113 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef MEMDATADEST_INC_H__ #define MEMDATADEST_INC_H__ #include #include #include #include #include "datadest.h" // This class is a DataDest that uses memory as the underlying output // source. See the documentation in datadest.h for the DataDest API. // The details below are specific to the MemDataDest and probably not // of direct interest to anyone writing model or texture export filters. class MemDataDest : public DataDest { public: // The MemDataDest does *NOT* take ownership of the memory pointer. MemDataDest( uint8_t * buf, size_t bufSize ); virtual ~MemDataDest(); virtual bool internalSeek( off_t offset ); virtual bool internalWrite( const uint8_t * buf, size_t bufLen ); size_t getDataLength() { return m_dataLen; } protected: private: uint8_t * m_buf; size_t m_bufSize; size_t m_bufOffset; size_t m_dataLen; }; #endif // MEMDATADEST_INC_H__ mm3d-1.3.7/src/libmm3d/rawtex.cc0000644000175000017500000001043510744511346013252 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "rawtex.h" #include #include #include "mm3dconfig.h" #include "log.h" using std::list; using std::string; RawTextureFilter::RawTextureFilter() { m_read.push_back( "RAW" ); m_write.push_back( "RAW" ); } RawTextureFilter::~RawTextureFilter() { } bool RawTextureFilter::canRead( const char * filename ) { if ( filename == NULL ) { return false; } string cmpstr; unsigned len = strlen( filename ); list::iterator it; for ( it = m_read.begin(); it != m_read.end(); it++ ) { cmpstr = string(".") + *it; if ( len >= cmpstr.length() ) { if ( strcasecmp( &filename[len-cmpstr.length()], cmpstr.c_str()) == 0 ) { return true; } } } return false; } Texture::ErrorE RawTextureFilter::readFile(Texture * texture, const char * filename) { log_debug( "filename is %s\n", filename ); FILE * fp; fp = fopen(filename, "rb"); const char * name = strrchr( filename, DIR_SLASH ); if ( name ) { texture->m_name = strdup( &name[1] ); } else { texture->m_name = strdup( filename ); } char * ext = strrchr( texture->m_name, '.' ); if ( ext ) { ext[0] = '\0'; } texture->m_filename = strdup( filename ); if ( fp == NULL ) { return Texture::ERROR_NO_FILE; } int32_t width = 0; int32_t height = 0; int32_t bytespp = 0; log_debug( "loading uncompressed RAW image file\n" ); int itemsRead = 0; itemsRead += fread(&width, sizeof(width), 1, fp); itemsRead += fread(&height, sizeof(height), 1, fp); itemsRead += fread(&bytespp, sizeof(bytespp), 1, fp); log_debug( "read %d items\n", itemsRead ); if ( itemsRead == 3 ) { if((width <= 0) || (height <= 0) || ((bytespp != 3) && (bytespp != 4))) { fprintf( stderr, "Invalid texture information (%d x %d x %d)\n", width, height, bytespp ); fclose(fp); return Texture::ERROR_BAD_DATA; } log_debug( "raw size: %d x %d, %d bytes per pixel\n", width, height, bytespp ); bool hasAlpha = (bytespp == 8); log_debug( "Alpha channel: %s\n", hasAlpha ? "present" : "not present" ); uint32_t imageSize = (bytespp * width * height); texture->m_data = new uint8_t[imageSize]; texture->m_format = hasAlpha ? Texture::FORMAT_RGBA : Texture::FORMAT_RGB; texture->m_width = width; texture->m_height = height; log_debug( "image size = %d\n", imageSize ); for ( int h = height; h > 0; h-- ) { if( fread( &texture->m_data[ (h-1) * width * bytespp ], width * bytespp, 1, fp) != 1 ) { fprintf( stderr, "Could not read image data" ); fclose(fp); return Texture::ERROR_UNEXPECTED_EOF; } } } else { if(fp != NULL) { fclose(fp); } return Texture::ERROR_BAD_DATA; } fclose(fp); return Texture::ERROR_NONE; } list RawTextureFilter::getReadTypes() { list rval; list::iterator it; for ( it = m_read.begin(); it != m_read.end(); it++ ) { rval.push_back( string("*.") + *it ); } return rval; } list RawTextureFilter::getWriteTypes() { list rval; list::iterator it; for ( it = m_write.begin(); it != m_write.end(); it++ ) { rval.push_back( string("*.") + *it ); } return rval; } mm3d-1.3.7/src/libmm3d/bsptree.cc0000644000175000017500000004556510744511346013420 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include #include #include #include "glheaders.h" #include "bsptree.h" #include "glmath.h" #include "log.h" #include "model.h" // Yes, it's hackish std::list< BspTree::Poly * > BspTree::Poly::s_recycle; std::list< BspTree::Node * > BspTree::Node::s_recycle; int BspTree::Poly::s_allocated = 0; int BspTree::Node::s_allocated = 0; void normalize( float * val ) { float mag = 0.0f; int t; for ( t = 0; t < 3; t++ ) { mag += val[t] * val[t]; } mag = sqrt( mag ); for ( t = 0; t < 3; t++ ) { val[t] = val[t] / mag; } } float dot_product( float * val1, float * val2 ) { return ( val1[0] * val2[0] ) + ( val1[1] * val2[1] ) + ( val1[2] * val2[2] ); } bool float_equiv( float rhs, float lhs ) { if ( fabs( rhs - lhs ) < 0.0001f ) { return true; } else { return false; } } static void _setMaterial( DrawingContext * context, int texture, Model::Material * material ) { glMaterialfv( GL_FRONT, GL_AMBIENT, material->m_ambient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, material->m_diffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, material->m_specular ); glMaterialfv( GL_FRONT, GL_EMISSION, material->m_emissive ); glMaterialf( GL_FRONT, GL_SHININESS, material->m_shininess ); context->m_currentTexture = texture; if ( material->m_type == Model::Material::MATTYPE_TEXTURE ) { glBindTexture( GL_TEXTURE_2D, context->m_textures[ context->m_currentTexture ] ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, material->m_sClamp ? GL_CLAMP : GL_REPEAT); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, material->m_tClamp ? GL_CLAMP : GL_REPEAT); } } int BspTree::Poly::s_nextId = 0; void BspTree::Poly::calculateNormal() { float A = coord[0][1] * (coord[1][2] - coord[2][2]) + coord[1][1] * (coord[2][2] - coord[0][2]) + coord[2][1] * (coord[0][2] - coord[1][2]); float B = coord[0][2] * (coord[1][0] - coord[2][0]) + coord[1][2] * (coord[2][0] - coord[0][0]) + coord[2][2] * (coord[0][0] - coord[1][0]); float C = coord[0][0] * (coord[1][1] - coord[2][1]) + coord[1][0] * (coord[2][1] - coord[0][1]) + coord[2][0] * (coord[0][1] - coord[1][1]); float len = sqrt((A * A) + (B * B) + (C * C)); norm[0] = A / len; norm[1] = B / len; norm[2] = C / len; calculateD(); //printf( "normal: %f %f %f\n", norm[0], norm[1], norm[2] ); //printf( "d: %f\n", d ); } void BspTree::Poly::calculateD() { d = dot_product( coord[0], norm ); } void BspTree::Poly::intersection( float * p1, float * p2, float * po, float & place ) { float interval = 0.25; float dtemp = 0.0f; place = 0.5f; bool greater = false; if ( dot_product( p2, norm ) > d ) { greater = true; } if ( dot_product( p1, norm ) > d ) { if ( greater ) { //printf( "no intersection!\n" ); return; } } else { if ( !greater ) { //printf( "no intersection!\n" ); return; } } float diff[3]; float oldPlace = place; diff[0] = p2[0] - p1[0]; diff[1] = p2[1] - p1[1]; diff[2] = p2[2] - p1[2]; do { po[0] = diff[0] * place + p1[0]; po[1] = diff[1] * place + p1[1]; po[2] = diff[2] * place + p1[2]; dtemp = dot_product( po, norm ); oldPlace = place; if ( greater ) { place += ( dtemp > d ) ? -interval : interval; } else { place += ( dtemp > d ) ? interval : -interval; } interval = interval * 0.5f; } while ( !float_equiv( d, dtemp ) ); place = oldPlace; } void BspTree::Poly::render( DrawingContext * context ) { //printf( "render triangle %d\n", id ); if ( context->m_currentTexture != texture ) { glEnd(); _setMaterial( context, texture, static_cast< Model::Material *>( material ) ); glBegin( GL_TRIANGLES ); } for ( int i = 0; i < 3; i++ ) { glTexCoord2f( s[ i ], t[ i ] ); glNormal3fv( drawNormals[i] ); glVertex3fv( coord[i] ); } } void BspTree::Poly::print() { //printf( "Poly %d\n", id ); //printf( " coord[0] = %f %f %f\n", coord[0][0], coord[0][1], coord[0][2] ); //printf( " coord[1] = %f %f %f\n", coord[1][0], coord[1][1], coord[1][2] ); //printf( " coord[2] = %f %f %f\n", coord[2][0], coord[2][1], coord[2][2] ); //printf( " n = %f %f %f\n", norm[0], norm[1], norm[2] ); } void BspTree::addPoly( BspTree::Poly * p ) { Node * n = Node::get(); n->self = p; if ( m_root == NULL ) { m_root = n; } else { m_root->addChild( n ); } } void BspTree::render( float * point, DrawingContext * context ) { if ( m_root ) { _setMaterial( context, m_root->self->texture, static_cast< Model::Material *>( m_root->self->material ) ); glEnable( GL_TEXTURE_2D ); glBegin( GL_TRIANGLES ); m_root->render( point, context ); glEnd(); } } void BspTree::clear() { if ( m_root ) { m_root->release(); m_root = NULL; } } BspTree::Poly * BspTree::Poly::get() { if ( !s_recycle.empty() ) { Poly * n = s_recycle.front(); s_recycle.pop_front(); return n; } else { return new Poly; } } void BspTree::Poly::release() { s_recycle.push_front( this ); } BspTree::Node * BspTree::Node::get() { if ( !s_recycle.empty() ) { Node * n = s_recycle.front(); s_recycle.pop_front(); n->self = NULL; n->left = NULL; n->right = NULL; return n; } else { return new Node; } } void BspTree::Node::release() { if ( left ) { left->release(); } if ( self ) { self->release(); } if ( right ) { right->release(); } s_recycle.push_front( this ); } void BspTree::Node::splitNodes( int idx1, int idx2, int idx3, float * p1, float * p2, BspTree::Node * n1, BspTree::Node * n2, const float & place1, const float & place2 ) { n1->self = Poly::get(); //printf( "split node poly: %d\n", n1->self->id ); for ( int i = 0; i < 3; i++ ) { n1->self->coord[0][i] = p1[i]; n1->self->coord[1][i] = self->coord[idx2][i]; n1->self->coord[2][i] = self->coord[idx3][i]; n1->self->drawNormals[0][i] = self->norm[i]; n1->self->drawNormals[1][i] = self->drawNormals[idx2][i]; n1->self->drawNormals[2][i] = self->drawNormals[idx3][i]; } n1->self->s[0] = (self->s[ idx2 ] - self->s[ idx1 ]) * place1 + self->s[ idx1 ]; n1->self->s[1] = self->s[ idx2 ]; n1->self->s[2] = self->s[ idx3 ]; n1->self->t[0] = (self->t[ idx2 ] - self->t[ idx1 ]) * place1 + self->t[ idx1 ]; n1->self->t[1] = self->t[ idx2 ]; n1->self->t[2] = self->t[ idx3 ]; n1->self->calculateNormal(); n1->self->texture = self->texture; n1->self->material = self->material; n2->self = Poly::get(); //printf( "split node poly: %d\n", n2->self->id ); for ( int i = 0; i < 3; i++ ) { n2->self->coord[0][i] = p1[i]; n2->self->coord[1][i] = self->coord[idx3][i]; n2->self->coord[2][i] = p2[i]; n2->self->drawNormals[0][i] = self->norm[i]; n2->self->drawNormals[1][i] = self->drawNormals[idx3][i]; n2->self->drawNormals[2][i] = self->norm[i]; } n2->self->s[0] = (self->s[ idx2 ] - self->s[ idx1 ]) * place1 + self->s[ idx1 ]; n2->self->s[1] = self->s[ idx3 ]; n2->self->s[2] = (self->s[ idx3 ] - self->s[ idx1 ]) * place2 + self->s[ idx1 ]; n2->self->t[0] = (self->t[ idx2 ] - self->t[ idx1 ]) * place1 + self->t[ idx1 ]; n2->self->t[1] = self->t[ idx3 ]; n2->self->t[2] = (self->t[ idx3 ] - self->t[ idx1 ]) * place2 + self->t[ idx1 ]; n2->self->calculateNormal(); n2->self->texture = self->texture; n2->self->material = self->material; for ( int i = 0; i < 3; i++ ) { self->coord[idx2][i] = p1[i]; self->coord[idx3][i] = p2[i]; self->drawNormals[idx2][i] = self->norm[i]; self->drawNormals[idx3][i] = self->norm[i]; } self->s[idx2] = (self->s[ idx2 ] - self->s[ idx1 ]) * place1 + self->s[ idx1 ]; self->s[idx3] = (self->s[ idx3 ] - self->s[ idx1 ]) * place2 + self->s[ idx1 ]; self->t[idx2] = (self->t[ idx2 ] - self->t[ idx1 ]) * place1 + self->t[ idx1 ]; self->t[idx3] = (self->t[ idx3 ] - self->t[ idx1 ]) * place2 + self->t[ idx1 ]; self->calculateD(); } void BspTree::Node::splitNode( int idx1, int idx2, int idx3, float * p1, BspTree::Node * n1, const float & place ) { n1->self = Poly::get(); //printf( "split node poly: %d\n", n1->self->id ); for ( int i = 0; i < 3; i++ ) { n1->self->coord[0][i] = self->coord[idx1][i]; n1->self->coord[1][i] = self->coord[idx2][i]; n1->self->coord[2][i] = p1[i]; n1->self->drawNormals[0][i] = self->drawNormals[idx1][i]; n1->self->drawNormals[1][i] = self->drawNormals[idx2][i]; n1->self->drawNormals[2][i] = self->norm[i]; } n1->self->s[0] = self->s[ idx1 ]; n1->self->s[1] = self->s[ idx2 ]; n1->self->s[2] = (self->s[ idx3 ] - self->s[ idx2 ]) * place + self->s[ idx2 ]; n1->self->t[0] = self->t[ idx1 ]; n1->self->t[1] = self->t[ idx2 ]; n1->self->t[2] = (self->t[ idx3 ] - self->t[ idx2 ]) * place + self->t[ idx2 ]; n1->self->calculateNormal(); n1->self->texture = self->texture; n1->self->material = self->material; for ( int i = 0; i < 3; i++ ) { self->coord[idx2][i] = p1[i]; self->drawNormals[idx2][i] = self->norm[i]; } self->s[idx2] = (self->s[ idx3 ] - self->s[ idx2 ]) * place + self->s[ idx2 ]; self->t[idx2] = (self->t[ idx3 ] - self->t[ idx2 ]) * place + self->t[ idx2 ]; self->calculateD(); } void BspTree::Node::addChild( Node * n ) { float d1 = dot_product( self->norm, n->self->coord[0] ); float d2 = dot_product( self->norm, n->self->coord[1] ); float d3 = dot_product( self->norm, n->self->coord[2] ); int i1 = 0; int i2 = 0; int i3 = 0; if ( !float_equiv( d1, self->d ) ) i1 = ( d1 < self->d ) ? -1 : 1; if ( !float_equiv( d2, self->d ) ) i2 = ( d2 < self->d ) ? -1 : 1; if ( !float_equiv( d3, self->d ) ) i3 = ( d3 < self->d ) ? -1 : 1; //printf( "self d = %f\n", self->d ); //printf( "addChild d = %f %f %f\n", d1, d2, d3 ); //printf( "addChild i = %d %d %d\n", i1, i2, i3 ); // This will catch co-plane also... which should be fine if ( i1 <= 0 && i2 <= 0 && i3 <= 0 ) { //printf( "add right\n" ); if ( left ) { left->addChild( n ); } else { left = n; } return; } if ( i1 >= 0 && i2 >= 0 && i3 >= 0 ) { //printf( "add left\n" ); if ( right ) { right->addChild( n ); } else { right = n; } return; } //printf( "split\n" ); float p1[3]; float p2[3]; float place1 = 0.0f; float place2 = 0.0f; if ( i1 == 0 || i2 == 0 || i3 == 0 ) { // one of the vertices is on the plane //printf( "split on vertex\n" ); Node * n1 = Node::get(); if ( i1 == 0 ) { self->intersection( n->self->coord[1], n->self->coord[2], p1, place1 ); n->splitNode( 0, 1, 2, p1, n1, place1 ); if ( i2 < 0 ) { if ( right ) addChild( n ); else right = n; if ( left ) left->addChild( n1 ); else left = n1; } else { if ( right ) addChild( n1 ); else right = n1; if ( left ) left->addChild( n ); else left = n; } } else if ( i2 == 0 ) { self->intersection( n->self->coord[2], n->self->coord[0], p1, place1 ); n->splitNode( 1, 2, 0, p1, n1, place1 ); if ( i1 < 0 ) { if ( right ) addChild( n1 ); else right = n1; if ( left ) left->addChild( n ); else left = n; } else { if ( right ) addChild( n ); else right = n; if ( left ) left->addChild( n1 ); else left = n1; } } else if ( i3 == 0 ) { self->intersection( n->self->coord[0], n->self->coord[1], p1, place1 ); n->splitNode( 2, 0, 1, p1, n1, place1 ); if ( i1 < 0 ) { if ( right ) addChild( n ); else right = n; if ( left ) left->addChild( n1 ); else left = n1; } else { if ( right ) addChild( n1 ); else right = n1; if ( left ) left->addChild( n ); else left = n; } } } else { Node * n1 = Node::get(); Node * n2 = Node::get(); if ( i1 == i2 ) { //printf( "split 1/2\n" ); self->intersection( n->self->coord[2], n->self->coord[0], p1, place1 ); self->intersection( n->self->coord[2], n->self->coord[1], p2, place2 ); //printf( "split at %f %f %f\n", p1[0], p1[1], p1[2] ); //printf( "split at %f %f %f\n", p2[0], p2[1], p2[2] ); n->splitNodes( 2, 0, 1, p1, p2, n1, n2, place1, place2 ); if ( i3 < 0 ) { n1->left = n2; if ( right ) right->addChild( n1 ); else right = n1; if ( left ) left->addChild( n ); else left = n; } else { n1->right = n2; if ( left ) left->addChild( n1 ); else left = n1; if ( right ) right->addChild( n ); else right = n; } } else if ( i1 == i3 ) { //printf( "split 1/3\n" ); self->intersection( n->self->coord[1], n->self->coord[2], p1, place1 ); self->intersection( n->self->coord[1], n->self->coord[0], p2, place2 ); //printf( "split at %f %f %f\n", p1[0], p1[1], p1[2] ); //printf( "split at %f %f %f\n", p2[0], p2[1], p2[2] ); n->splitNodes( 1, 2, 0, p1, p2, n1, n2, place1, place2 ); if ( i2 < 0 ) { n1->left = n2; if ( right ) right->addChild( n1 ); else right = n1; if ( left ) left->addChild( n ); else left = n; } else { n1->right = n2; if ( left ) left->addChild( n1 ); else left = n1; if ( right ) right->addChild( n ); else right = n; } } else if ( i2 == i3 ) { self->intersection( n->self->coord[0], n->self->coord[1], p1, place1 ); self->intersection( n->self->coord[0], n->self->coord[2], p2, place2 ); n->splitNodes( 0, 1, 2, p1, p2, n1, n2, place1, place2 ); if ( i1 < 0 ) { n1->left = n2; if ( right ) right->addChild( n1 ); else right = n1; if ( left ) left->addChild( n ); else left = n; } else { n1->right = n2; if ( left ) left->addChild( n1 ); else left = n1; if ( right ) right->addChild( n ); else right = n; } } } } void BspTree::Node::render( float * point, DrawingContext * context ) { float d = dot_product( self->norm, point ); if ( d < self->d ) { if ( right ) { right->render( point, context ); } self->render( context ); if ( left ) { left->render( point, context ); } } else { if ( left ) { left->render( point, context ); } self->render( context ); if ( right ) { right->render( point, context ); } } } void BspTree::Poly::stats() { log_debug( "BspTree::Poly: %d/%d\n", s_recycle.size(), s_allocated ); } void BspTree::Node::stats() { log_debug( "BspTree::Node: %d/%d\n", s_recycle.size(), s_allocated ); } int BspTree::Poly::flush() { int c = 0; std::list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } int BspTree::Node::flush() { int c = 0; std::list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } #if 0 int main( int argc, char * argv[] ) { char input[128]; BspTree tree; while ( fgets( input, sizeof(input), stdin ) ) { float coord[0][3]; float coord[1][3]; float coord[2][3]; if ( input[0] == 'c' ) { printf( "camera\n" ); if ( sscanf(&input[1], "%f %f %f", &coord[0][0], &coord[0][1], &coord[0][2] ) == 3 ) { printf( "got camera point\n" ); tree.render( coord[0] ); } } else if ( sscanf( input, "%f %f %f %f %f %f %f %f %f", &coord[0][0], &coord[0][1], &coord[0][2], &coord[1][0], &coord[1][1], &coord[1][2], &coord[2][0], &coord[2][1], &coord[2][2] ) == 9 ) { Poly * p = Poly::get(); printf( "read poly: %d\n", p->id ); for ( int i = 0; i < 3; i++ ) { p->coord[0][i] = coord[0][i]; p->coord[1][i] = coord[1][i]; p->coord[2][i] = coord[2][i]; } p->calculateNormal(); tree.addPoly( p ); } } return 0; } #endif // 0 mm3d-1.3.7/src/libmm3d/local_ptr.h0000644000175000017500000000324710744511346013564 00000000000000/* Misfit Model 3D * * Copyright (c) 2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __LOCAL_PTR_H #define __LOCAL_PTR_H #include template class local_ptr { public: local_ptr( T * pval = NULL ) : m_pval( pval ) {} ~local_ptr() { free_ptr(); } T * get() { return m_pval; } T * reset(T * newPval) { free_ptr(); return m_pval = newPval; } const T * get() const { return m_pval; } T & operator*() { return *m_pval; } T * operator->() { return m_pval; } const T & operator*() const { return *m_pval; } const T * operator->() const { return m_pval; } T * operator=(T* newPval) { return reset(newPval); } bool operator!() const { return m_pval == NULL; } bool isnull() const { return m_pval == NULL; } protected: void free_ptr() { delete m_pval; m_pval = NULL; } T * m_pval; }; #endif // __LOCAL_PTR_H mm3d-1.3.7/src/libmm3d/ms3dfilter.h0000644000175000017500000000623511000471707013651 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __MS3DFILTER_H #define __MS3DFILTER_H #include "modelfilter.h" #include "mesh.h" class Ms3dFilter : public ModelFilter { public: class Ms3dOptions : public ModelFilter::Options { public: Ms3dOptions(); virtual void release() { delete this; }; int m_subVersion; uint32_t m_vertexExtra; uint32_t m_jointColor; void setOptionsFromModel( Model * m ); protected: virtual ~Ms3dOptions(); // Use release() instead }; Ms3dFilter() : ModelFilter(), m_options(NULL) {}; virtual ~Ms3dFilter() {}; struct _VertexWeight_t { int boneId; int weight; }; typedef struct _VertexWeight_t VertexWeightT; typedef std::list VertexWeightList; enum _CommentType_e { CT_GROUP, CT_MATERIAL, CT_JOINT, CT_MODEL, CT_MAX, }; typedef enum _CommentType_e CommentTypeE; Model::ModelErrorE readFile( Model * model, const char * const filename ); Model::ModelErrorE writeFile( Model * model, const char * const filename, ModelFilter::Options * o = NULL ); Options * getDefaultOptions() { return new Ms3dOptions; }; bool canRead( const char * filename = NULL ) { return true; }; bool canWrite( const char * filename = NULL ) { return true; }; bool canExport( const char * filename = NULL ) { return true; }; bool isSupported( const char * filename ); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); protected: void readString( char * buf, size_t len ); bool readCommentSection(); bool readVertexWeightSection(); bool readVertexWeight( int subVersion, int vertex, VertexWeightList & weightList ); void writeCommentSection(); void writeVertexWeightSection( const MeshList & ml ); void writeJointColorSection(); // The InfluenceList must be sorted before calling this function void writeVertexWeight( int subVersion, const Model::InfluenceList & ilist ); DataDest * m_dst; DataSource * m_src; Model * m_model; Ms3dOptions * m_options; static char const MAGIC_NUMBER[]; }; #endif // __MS3DFILTER_H mm3d-1.3.7/src/libmm3d/model.h0000644000175000017500000022515411000471707012700 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __MODEL_H #define __MODEL_H #include "glheaders.h" #include "glmath.h" #include "bsptree.h" #include "drawcontext.h" #include "sorted_list.h" #ifdef MM3D_EDIT #include "undomgr.h" #endif // MM3D_EDIT #include #include #include #include #include #include using std::list; using std::vector; class Texture; // Warning: Here be dragons. // // The Model class is the core of MM3D. It contains both the oldest code and // the newest code. Some very early design decisions were bad decisions. Some of // those bad decisions are still here causing headaches. I've tried to add some // documentation to this header file. Despite that, the best way to understand // how to use the model class is to find reference code elsewhere in MM3D that // does something similar to what you want to do. // // The model represents everything about how the model is rendered as well as some // properties that are not visible to the user. A model primitive is any sub-object // within the model (vertices, triangles, bone joints, points, texture projections, // etc). // // All faces in the Model are triangles. // // A group can be thought of as a mesh made up of triangles. Materials can be // assigned to groups (so all triangles in the group share the same material). // Unlike meshes in some implementations, vertices in MM3D models may be shared // by triangles in different groups. // // A material defines how lighting is reflected off of a group of faces. A material // may have an associated texture for texture mapping. Occasionally you will see // the term "texture" used where "material" is meant. // // The Model implementation is split among several C++ files, listed below: // // model.cc: A catch-all for core Model functionality. // model_anim.cc: Animation // model_bool.cc: Boolean operations (union, subtract, intersect) // model_draw.cc: Visual rendering of the model // model_group.cc: Group/Mesh-related functionality // model_influence.cc: Bone joint influences on vertices and points // model_inner.cc: Core functionality for Model's inner classes // model_insert.cc: Undo/redo book-keeping for adjusting indices in primitive lists // model_meta.cc: MetaData methods // model_ops.cc: Model comparison, merging, simplification // model_proj.cc: Texture projections // model_select.cc: Selection logic // model_test.cc: Old tests for file format loading/saving, being replaced // model_texture.cc: Material and texture code // // TODO rename Texture -> Material where appropriate // TODO Make texture creation more consistent class Model { public: // ChangeBits is used to tell Model::Observer objects what has changed // about the model. enum ChangeBits { SelectionChange = 0x00000001, // General selection change SelectionVertices = 0x00000002, // Vertices selection changed SelectionFaces = 0x00000004, // Faces selection changed SelectionGroups = 0x00000008, // Groups selection changed SelectionJoints = 0x00000010, // Joints selection changed SelectionPoints = 0x00000020, // Points selection changed AddGeometry = 0x00000100, // Added or removed objects AddAnimation = 0x00000200, // Added or removed animations AddOther = 0x00008000, // Added or removed something else MoveGeometry = 0x00010000, // Model shape changed MoveOther = 0x00080000, // Something non-geometric was moved AnimationMode = 0x00010000, // Changed animation mode AnimationSet = 0x00020000, // Changes to animation sets AnimationFrame = 0x00080000, // Changed current animation frame ChangeAll = 0xFFFFFFFF // All of the above }; // FIXME remove this when new equal routines are ready enum CompareBits { CompareGeometry = 0x01, // Vertices and Faces match CompareFaces = 0x02, // Faces match, vertices may not CompareGroups = 0x04, // Groups match CompareSkeleton = 0x08, // Bone joints hierarchy matches CompareMaterials = 0x10, // Material properties and group material assignments match CompareAnimSets = 0x20, // Number of animations, frame counts, and fps match CompareAnimData = 0x40, // Animation movements match CompareMeta = 0x80, // Names and other non-visible data match ComparePoints = 0x100, // Points match CompareInfluences = 0x200, // Vertex and point influences match CompareTextures = 0x400, // Texture coordinates and texture data match CompareAll = 0xFFFF // All of the above }; enum ComparePartsE { PartVertices = 0x0001, // PartFaces = 0x0002, // PartGroups = 0x0004, // PartMaterials = 0x0008, // PartTextures = 0x0010, // PartJoints = 0x0020, // PartPoints = 0x0040, // PartProjections = 0x0080, // PartBackgrounds = 0x0100, // PartMeta = 0x0200, // PartSkelAnims = 0x0400, // PartFrameAnims = 0x0800, // PartFormatData = 0x1000, // PartFilePaths = 0x2000, // PartAll = 0xFFFF, // // These are combinations of parts above, for convenience PartGeometry = PartVertices | PartFaces | PartGroups, // PartTextureMap = PartFaces | PartGroups | PartMaterials | PartTextures | PartProjections, // PartAnimations = PartSkelAnims | PartFrameAnims, // }; enum PartPropertiesE { PropName = 0x000001, // PropType = 0x000002, // PropSelection = 0x000004, // PropVisibility = 0x000008, // PropFree = 0x000010, // PropCoords = 0x000020, // PropRotation = 0x000040, // PropScale = 0x000080, // PropInfluences = 0x000100, // PropWeights = 0x000200, // PropNormals = 0x000400, // PropTexCoords = 0x000800, // PropMaterials = 0x001000, // PropProjections = 0x002000, // PropVertices = 0x004000, // PropPoints = 0x008000, // PropTriangles = 0x010000, // PropLighting = 0x020000, // PropClamp = 0x040000, // PropPaths = 0x080000, // PropDimensions = 0x100000, // PropPixels = 0x200000, // PropTime = 0x400000, // PropAll = 0xFFFFFF, // // These are combinations of parts above, for convenience PropFlags = PropSelection | PropVisibility | PropFree, }; enum { MAX_INFLUENCES = 4 }; enum _PositionType_e { PT_Vertex, PT_Joint, PT_Point, PT_Projection }; typedef enum _PositionType_e PositionTypeE; enum _OperationScope_e { OS_Selected, OS_Global }; typedef enum _OperationScope_e OperationScopeE; enum _TextureProjectionType_e { TPT_Custom = -1, // No projection TPT_Cylinder = 0, TPT_Sphere = 1, TPT_Plane = 2, TPT_Icosahedron = 3, // Not yet implemented TPT_MAX }; typedef enum _TextureProjectionType_e TextureProjectionTypeE; enum _InfluenceType_e { IT_Custom = 0, IT_Auto, IT_Remainder, IT_MAX }; typedef enum _InfluenceType_e InfluenceTypeE; struct _Influence_t { int m_boneId; InfluenceTypeE m_type; double m_weight; bool operator==( const struct _Influence_t & rhs ) const { return m_boneId == rhs.m_boneId && m_type == rhs.m_type && fabs( m_weight - rhs.m_weight ) < 0.00001; } bool operator!=( const struct _Influence_t & rhs ) const { return ! (*this == rhs ); } bool operator<( const struct _Influence_t & rhs ) const { if ( fabs( m_weight - rhs.m_weight ) < 0.00001 ) return m_boneId < rhs.m_boneId; return m_weight < rhs.m_weight; } }; typedef struct _Influence_t InfluenceT; typedef std::list< InfluenceT > InfluenceList; // A position is a common way to manipulate any object that has a // single position value. See the PositionTypeE values. // The index property is the index in the the list that corresponds // to the type. class Position { public: PositionTypeE type; unsigned index; }; // A vertex defines a polygon corner. The position is in m_coord. // All triangles in all groups (meshes) references triangles from this // one list. class Vertex { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static Vertex * get(); void release(); void sprint( std::string & dest ); double m_coord[3]; // Absolute vertex location double m_kfCoord[3]; // Animated position bool m_selected; bool m_visible; bool m_marked; bool m_marked2; // If m_free is false, the vertex will be implicitly deleted when // all faces using it are deleted bool m_free; double * m_drawSource; // Points to m_coord or m_kfCoord for drawing // List of bone joints that move the vertex in skeletal animations. InfluenceList m_influences; bool propEqual( const Vertex & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==( const Vertex & rhs ) const { return propEqual( rhs ); } protected: Vertex(); virtual ~Vertex(); void init(); static list s_recycle; static int s_allocated; }; // A triangle represents faces in the model. All faces are triangles. // The vertices the triangle is attached to are in m_vertexIndices. class Triangle { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static Triangle * get(); void release(); void sprint( std::string & dest ); unsigned m_vertexIndices[3]; // Texture coordinate 0,0 is in the lower left corner of // the texture. float m_s[3]; // Horizontal, one for each vertex. float m_t[3]; // Vertical, one for each vertex. double m_finalNormals[3][3]; // Final normals to draw double m_vertexNormals[3][3]; // Normals blended for each face attached to the vertex double m_flatNormals[3]; // Normal for this triangle double m_kfFlatNormals[3]; // Flat normal, rotated relative to the animating bone joints double m_kfNormals[3][3]; // Final normals, rotated relative to the animating bone joints double * m_flatSource; // Either m_flatNormals or m_kfFlatNormals double * m_normalSource[3]; // Either m_finalNormals or m_kfNormals bool m_selected; bool m_visible; bool m_marked; bool m_marked2; bool m_userMarked; int m_projection; // Index of texture projection (-1 for none) bool propEqual( const Triangle & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==( const Triangle & rhs ) const { return propEqual( rhs ); } protected: Triangle(); virtual ~Triangle(); void init(); static list s_recycle; static int s_allocated; }; // Group of triangles. All triangles in a group share a material (if one // is assigned to the Group). Vertices assigned to the triangles may // be shared between triangles in different groups. You can change how // normals are blended by modifying m_angle and m_smooth. class Group { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static Group * get(); void release(); void sprint( std::string & dest ); std::string m_name; int m_materialIndex; // Material index (-1 for none) std::set m_triangleIndices; // List of triangles in this group // Percentage of blending between flat normals and smooth normals // 0 = 0%, 255 = 100% uint8_t m_smooth; // Maximum angle around which triangle normals will be blended // (ie, if m_angle = 90, triangles with an edge that forms an // angle greater than 90 will not be blended). uint8_t m_angle; bool m_selected; bool m_visible; bool m_marked; bool propEqual( const Group & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const Group & rhs ) const { return propEqual( rhs ); } protected: Group(); virtual ~Group(); void init(); static list s_recycle; static int s_allocated; }; // The Material defines how lighting is reflected off of triangles and // may include a texture map. class Material { public: enum _MaterialType_e { MATTYPE_TEXTURE = 0, // Texture mapped material MATTYPE_BLANK = 1, // Blank texture, lighting only MATTYPE_COLOR = 2, // Unused MATTYPE_GRADIENT = 3, // Unused MATTYPE_MAX = 4 // For convenience }; typedef enum _MaterialType_e MaterialTypeE; static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static Material * get(); void release(); void sprint( std::string & dest ); std::string m_name; MaterialTypeE m_type; // See MaterialTypeE above // Lighting values (RGBA, 0.0 to 1.0) float m_ambient[4]; float m_diffuse[4]; float m_specular[4]; float m_emissive[4]; // Lighting value 0 to 100.0 float m_shininess; uint8_t m_color[4][4]; // Unused // The clamp properties determine if the texture map wraps when crossing // the 0.0 or 1.0 boundary (false) or if the pixels along the edge are // used for coordinates outside the 0.0 - 1.0 limits (true). bool m_sClamp; // horizontal wrap/clamp bool m_tClamp; // vertical wrap/clamp // Open GL texture index (not actually used in model editing // viewports since each viewport needs its own texture index) GLuint m_texture; std::string m_filename; // Absolute path to texture file (for MATTYPE_TEXTURE) std::string m_alphaFilename; // Unused Texture * m_textureData; // Texture data (for MATTYPE_TEXTURE) bool propEqual( const Material & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const Material & rhs ) const { return propEqual( rhs ); } protected: Material(); virtual ~Material(); void init(); static list s_recycle; static int s_allocated; }; // A keyframe for a single joint in a single frame. Keyframes may be rotation or // translation (you can set one without setting the other). class Keyframe { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static Keyframe * get(); void release(); void sprint( std::string & dest ); int m_jointIndex; // Joint that this keyframe affects unsigned m_frame; // Frame number for this keyframe double m_time; // Time for this keyframe in seconds double m_parameter[3]; // Translation or rotation (radians), see m_isRotation bool m_isRotation; // Indicates if m_parameter describes rotation (true) or translation (false) bool operator<( const Keyframe & rhs ) const { return ( this->m_frame < rhs.m_frame || (this->m_frame == rhs.m_frame && !this->m_isRotation && rhs.m_isRotation) ); }; bool operator==( const Keyframe & rhs ) const { return ( this->m_frame == rhs.m_frame && this->m_isRotation == rhs.m_isRotation ); }; bool propEqual( const Keyframe & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; protected: Keyframe(); virtual ~Keyframe(); void init(); static list s_recycle; static int s_allocated; }; // A bone joint in the skeletal structure, used for skeletal animations. // When a vertex or point is assigned to one or more bone joints with a specified // weight, the joint is referred to as an Influence. class Joint { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static Joint * get(); void release(); void sprint( std::string & dest ); std::string m_name; double m_localRotation[3]; // Rotation relative to parent joint (or origin if no parent) double m_localTranslation[3]; // Translation relative to parent joint (or origin if no parent) Matrix m_absolute; // Absolute matrix for the joint's original position and orientation Matrix m_relative; // Matrix relative to parent joint Matrix m_final; // Final animated absolute position for bone joint int m_currentRotationKeyframe; // Unused int m_currentTranslationKeyframe; // Unused int m_parent; // Parent joint index (-1 for no parent) bool m_selected; bool m_visible; bool m_marked; bool propEqual( const Joint & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const Joint & rhs ) const { return propEqual( rhs ); } protected: Joint(); virtual ~Joint(); void init(); static list s_recycle; static int s_allocated; }; class Point { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static Point * get(); void release(); void sprint( std::string & dest ); std::string m_name; int m_type; double m_trans[3]; // Position double m_rot[3]; // Rotation double m_kfTrans[3]; // Animated position double m_kfRot[3]; // Animated rotation // These pointers point to the unanimated or animated properties // depending on whether or not the model is animated when it is drawn. double * m_drawSource; // m_trans or m_kfTrans double * m_rotSource; // m_rot or m_kfRot bool m_selected; bool m_visible; bool m_marked; // List of bone joints that move the point in skeletal animations. InfluenceList m_influences; bool propEqual( const Point & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const Point & rhs ) const { return propEqual( rhs ); } protected: Point(); virtual ~Point(); void init(); static list s_recycle; static int s_allocated; }; // A TextureProjection is used automatically map texture coordinates to a group // of vertices. Common projection types are Sphere, Cylinder, and Plane. class TextureProjection { public: static int flush(); static int allocated() { return s_allocated; } static void stats(); static TextureProjection * get(); void release(); void sprint( std::string & dest ); std::string m_name; int m_type; // See TextureProjectionTypeE double m_pos[3]; double m_upVec[3]; // Vector that defines "up" for this projection double m_seamVec[3]; // Vector that indicates where the texture wraps from 1.0 back to 0.0 double m_range[2][2]; // min/max, x/y bool m_selected; bool m_marked; bool propEqual( const TextureProjection & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const TextureProjection & rhs ) const { return propEqual( rhs ); } protected: TextureProjection(); virtual ~TextureProjection(); void init(); static int s_allocated; }; // TODO: Probably should use a map for the KeyframeList typedef sorted_ptr_list KeyframeList; typedef vector JointKeyframeList; // Describes a skeletal animation. class SkelAnim { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static SkelAnim * get(); void release(); void releaseData(); void sprint( std::string & dest ); std::string m_name; JointKeyframeList m_jointKeyframes; double m_fps; // Frames per second double m_spf; // Seconds per frame (for convenience, 1.0 / m_fps) unsigned m_frameCount; // Number of frames in the animation bool m_validNormals; // Whether or not the normals have been calculated for the current animation frame bool propEqual( const SkelAnim & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const SkelAnim & rhs ) const { return propEqual( rhs ); } protected: SkelAnim(); virtual ~SkelAnim(); void init(); static list s_recycle; static int s_allocated; }; // Describes the position and normal for a vertex in a frame animation. class FrameAnimVertex { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static FrameAnimVertex * get(); void release(); void sprint( std::string & dest ); double m_coord[3]; double m_normal[3]; bool propEqual( const FrameAnimVertex & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const FrameAnimVertex & rhs ) const { return propEqual( rhs ); } protected: FrameAnimVertex(); virtual ~FrameAnimVertex(); void init(); static list s_recycle; static int s_allocated; }; typedef vector FrameAnimVertexList; // Describes the position and orientation for a point in a frame animation. class FrameAnimPoint { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static FrameAnimPoint * get(); void release(); void sprint( std::string & dest ); double m_trans[3]; double m_rot[3]; bool propEqual( const FrameAnimPoint & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const FrameAnimPoint & rhs ) const { return propEqual( rhs ); } protected: FrameAnimPoint(); virtual ~FrameAnimPoint(); void init(); static list s_recycle; static int s_allocated; }; typedef vector FrameAnimPointList; // Contains the list of vertex positions and point positions for each vertex // and point for one animation frame. class FrameAnimData { public: FrameAnimData() : m_frameVertices(NULL), m_framePoints(NULL) {} FrameAnimVertexList * m_frameVertices; FrameAnimPointList * m_framePoints; void releaseData(); bool propEqual( const FrameAnimData & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const FrameAnimData & rhs ) const { return propEqual( rhs ); } }; typedef vector< FrameAnimData *> FrameAnimDataList; // Describes a frame animation (also known as "Mesh Deformation Animation"). // This object contains a list of vertex positions for each vertex for every // frame (and also every point for every frame). class FrameAnim { public: static int flush(); static int allocated() { return s_allocated; } static int recycled() { return s_recycle.size(); } static void stats(); static FrameAnim * get(); void release(); void releaseData(); void sprint( std::string & dest ); std::string m_name; // Each element in m_frameData is one frame. The frames hold lists of // all vertex positions and point positions. FrameAnimDataList m_frameData; double m_fps; // Frames per second bool m_validNormals; // Whether or not the normals have been calculated bool propEqual( const FrameAnim & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const FrameAnim & rhs ) const { return propEqual( rhs ); } protected: FrameAnim(); virtual ~FrameAnim(); void init(); static list s_recycle; static int s_allocated; }; // Working storage for an animated vertex. class KeyframeVertex { public: double m_coord[3]; double m_normal[3]; double m_rotatedNormal[3]; }; // Working storage for an animated triangle. class KeyframeTriangle { public: double m_normals[3][3]; }; // Reference background images for canvas viewports. class BackgroundImage { public: BackgroundImage(); virtual ~BackgroundImage(); void sprint( std::string & dest ); std::string m_filename; float m_scale; // 1.0 means 1 GL unit from the center to the edges of the image float m_center[3]; // Point in the viewport where the image is centered bool propEqual( const BackgroundImage & rhs, int propBits = PropAll, double tolerance = 0.00001 ) const; bool operator==(const BackgroundImage & rhs ) const { return propEqual( rhs ); } }; typedef Model::Vertex * VertexPtr; typedef Model::Triangle * TrianglePtr; typedef Model::Group * GroupPtr; typedef Model::Material * MaterialPtr; //typedef Model::Joint * JointPtr; // FormatData is used to store data that is used by specific file formats // that is not understood by MM3D. class FormatData { public: FormatData() : offsetType( 0 ), format( "" ), index( 0 ), len( 0 ), data( NULL ) { }; virtual ~FormatData(); uint16_t offsetType; // 0 = none, is valid std::string format; // Should not be empty uint32_t index; // for formats with multiple data sets uint32_t len; // length of data in 'data' uint8_t * data; // pointer to data virtual void serialize(); }; // Arbitrary key/value string pairs. This is used to provide a simple interface // for model attributes that are not manipulated by commands/tools. Often // user-editable format-specific data is stored as MetaData key/value pairs // (for example texture paths in MD2 and MD3 models). class MetaData { public: std::string key; std::string value; }; typedef std::vector< MetaData > MetaDataList; // See errorToString() enum _ModelError_e { ERROR_NONE = 0, ERROR_CANCEL, ERROR_UNKNOWN_TYPE, ERROR_UNSUPPORTED_OPERATION, ERROR_BAD_ARGUMENT, ERROR_NO_FILE, ERROR_NO_ACCESS, ERROR_FILE_OPEN, ERROR_FILE_READ, ERROR_BAD_MAGIC, ERROR_UNSUPPORTED_VERSION, ERROR_BAD_DATA, ERROR_UNEXPECTED_EOF, ERROR_FILTER_SPECIFIC, ERROR_EXPORT_ONLY, ERROR_UNKNOWN }; typedef enum _ModelError_e ModelErrorE; enum _SelectionMode_e { SelectNone, SelectVertices, SelectTriangles, SelectConnected, SelectGroups, SelectJoints, SelectPoints, SelectProjections, }; typedef enum _SelectionMode_e SelectionModeE; // Canvas drawing projections (not related to TextureProjections) enum _ProjectionDirection_e { View3d = 0, ViewFront, ViewBack, ViewLeft, ViewRight, ViewTop, ViewBottom }; typedef enum _ProjectionDirection_e ProjectionDirectionE; enum { MAX_GROUP_NAME_LEN = 32, MAX_BACKGROUND_IMAGES = 6 }; // Drawing options. These are defined as powers of 2 so that they // can be combined with a bitwise OR. enum { DO_NONE = 0x00, DO_TEXTURE = 0x01, DO_SMOOTHING = 0x02, // Normal smoothing/blending between faces DO_WIREFRAME = 0x04, DO_BADTEX = 0x08, // Render bad textures, or render as no texture DO_ALPHA = 0x10, // Do alpha blending DO_BACKFACECULL = 0x20, // Do not render triangles that face away from the camera }; enum _AnimationMode_e { ANIMMODE_NONE = 0, ANIMMODE_SKELETAL, ANIMMODE_FRAME, ANIMMODE_FRAMERELATIVE, // Not implemented ANIMMODE_MAX }; typedef enum _AnimationMode_e AnimationModeE; enum _DrawJointMode_e { JOINTMODE_NONE = 0, JOINTMODE_LINES, JOINTMODE_BONES, JOINTMODE_MAX }; typedef enum _DrawJointMode_e DrawJointModeE; enum _AnimationMerge_e { AM_NONE = 0, AM_ADD, AM_MERGE }; typedef enum _AnimationMerge_e AnimationMergeE; enum _BooleanOp_e { BO_Union, BO_UnionRemove, BO_Subtraction, BO_Intersection, BO_MAX }; typedef enum _BooleanOp_e BooleanOpE; #ifdef MM3D_EDIT // Register an observer if you have an object that must be notified when the // model changes. The modelChanged function will be called with changeBits // set to describe (in general terms) what changed. See ChangeBits. class Observer { public: virtual ~Observer(); virtual void modelChanged( int changeBits ) = 0; }; typedef std::list< Observer * > ObserverList; #endif // MM3D_EDIT // ================================================================== // Public methods // ================================================================== Model(); virtual ~Model(); static const char * errorToString( Model::ModelErrorE, Model * model = NULL ); static bool operationFailed( Model::ModelErrorE ); // Returns if models are visually equivalent bool equivalent( const Model * model, double tolerance = 0.00001 ) const; // Compares if two models are equal. Returns true of all specified // properties of all specified parts match. See ComparePartsE and // PartPropertiesE. bool propEqual( const Model * model, int partBits = PartAll, int propBits = PropAll, double tolerance = 0.00001 ) const; void sprint( std::string & dest ); // ------------------------------------------------------------------ // "Meta" data, model information that is not rendered in a viewport. // ------------------------------------------------------------------ // Indicates if the model has changed since the last time it was saved. void setSaved( bool o ) { if ( o ) { m_undoMgr->setSaved(); }; }; bool getSaved() const { return m_undoMgr->isSaved(); }; const char * getFilename() const { return m_filename.c_str(); }; void setFilename( const char * filename ) { if ( filename && filename[0] ) { m_filename = filename; } }; const char * getExportFile() const { return m_exportFile.c_str(); }; void setExportFile( const char * filename ) { if ( filename && filename[0] ) { m_exportFile = filename; } }; void setFilterSpecificError( const char * str ) { s_lastFilterError = m_filterSpecificError = str; }; const char * getFilterSpecificError() const { return m_filterSpecificError.c_str(); }; static const char * getLastFilterSpecificError() { return s_lastFilterError.c_str(); }; // Observers are notified when the model changes. See the Observer class // for details. void addObserver( Observer * o ); void removeObserver( Observer * o ); // See the MetaData class. void addMetaData( const char * key, const char * value ); void updateMetaData( const char * key, const char * value ); // Look-up by key bool getMetaData( const char * key, char * value, size_t valueLen ) const; // Look-up by index bool getMetaData( unsigned int index, char * key, size_t keyLen, char * value, size_t valueLen ) const; unsigned int getMetaDataCount() const; void clearMetaData(); void removeLastMetaData(); // For undo only! // Background image accessors. See the BackgroundImage class. void setBackgroundImage( unsigned index, const char * str ); void setBackgroundScale( unsigned index, float scale ); void setBackgroundCenter( unsigned index, float x, float y, float z ); const char * getBackgroundImage( unsigned index ) const; float getBackgroundScale( unsigned index ) const; void getBackgroundCenter( unsigned index, float & x, float & y, float & z ) const; // These are used to store status messages when the model does not have a status // bar. When a model is assigned to a viewport window, the messages will be // displayed in the status bar. bool hasErrors() const { return !m_loadErrors.empty(); } void pushError( const std::string & err ); std::string popError(); // Use these functions to preserve data that Misfit doesn't support natively int addFormatData( FormatData * fd ); bool deleteFormatData( unsigned index ); unsigned getFormatDataCount() const; FormatData * getFormatData( unsigned index ) const; FormatData * getFormatDataByFormat( const char * format, unsigned index = 0 ) const; // not case sensitive // ------------------------------------------------------------------ // Rendering functions // ------------------------------------------------------------------ // Functions for rendering the model in a viewport void draw( unsigned drawOptions = DO_TEXTURE, ContextT context = NULL, float *viewPoint = NULL ); void drawLines(); void drawVertices(); void drawPoints(); void drawProjections(); void drawJoints(); void setCanvasDrawMode( int m ) { m_canvasDrawMode = m; }; int getCanvasDrawMode() const { return m_canvasDrawMode; }; void setDrawJoints( DrawJointModeE m ) { m_drawJoints = m; }; DrawJointModeE getDrawJoints() const { return m_drawJoints; }; void setDrawProjections( bool o ) { m_drawProjections = o; }; bool getDrawProjections() const { return m_drawProjections; }; // Open GL needs textures allocated for each viewport that renders the textures. // A ContextT associates a set of OpenGL textures with a viewport. bool loadTextures( ContextT context = NULL ); void removeContext( ContextT context ); // Forces a reload and re-initialization of all textures in all // viewports (contexts) void invalidateTextures(); // Counter that indicates how many OpenGL textures are currently allocated. static int s_glTextures; // The local matrix is used by non-mm3d applications that use this // library to render MM3D models. In MM3D it should always be set to the // identity matrix. Other apps use it to move an animated model to a new // location in space, it only affects rendering of skeletal animations. void setLocalMatrix( const Matrix & m ) { m_localMatrix = m; }; // ------------------------------------------------------------------ // Animation functions // ------------------------------------------------------------------ bool setCurrentAnimation( AnimationModeE m, const char * name ); bool setCurrentAnimation( AnimationModeE m, unsigned index ); bool setCurrentAnimationFrame( unsigned frame ); bool setCurrentAnimationTime( double time ); unsigned getCurrentAnimation() const; unsigned getCurrentAnimationFrame() const; double getCurrentAnimationTime() const; void setAnimationLooping( bool o ); bool isAnimationLooping() const; // Stop animation mode, go back to standard pose editing. void setNoAnimation(); AnimationModeE getAnimationMode() const { return m_animationMode; }; bool inSkeletalMode() const { return (m_animationMode == ANIMMODE_SKELETAL); }; // Common animation properties int addAnimation( AnimationModeE mode, const char * name ); void deleteAnimation( AnimationModeE mode, unsigned index ); unsigned getAnimCount( AnimationModeE m ) const; const char * getAnimName( AnimationModeE mode, unsigned anim ) const; bool setAnimName( AnimationModeE mode, unsigned anim, const char * name ); double getAnimFPS( AnimationModeE mode, unsigned anim ) const; bool setAnimFPS( AnimationModeE mode, unsigned anim, double fps ); unsigned getAnimFrameCount( AnimationModeE mode, unsigned anim ) const; bool setAnimFrameCount( AnimationModeE mode, unsigned anim, unsigned count ); bool clearAnimFrame( AnimationModeE mode, unsigned anim, unsigned frame ); // Frame animation geometry void setFrameAnimVertexCount( unsigned vertexCount ); void setFrameAnimPointCount( unsigned pointCount ); bool setFrameAnimVertexCoords( unsigned anim, unsigned frame, unsigned vertex, double x, double y, double z ); bool getFrameAnimVertexCoords( unsigned anim, unsigned frame, unsigned vertex, double & x, double & y, double & z ) const; bool getFrameAnimVertexNormal( unsigned anim, unsigned frame, unsigned vertex, double & x, double & y, double & z ) const; // Not undo-able bool setQuickFrameAnimVertexCoords( unsigned anim, unsigned frame, unsigned vertex, double x, double y, double z ); bool setFrameAnimPointCoords( unsigned anim, unsigned frame, unsigned point, double x, double y, double z ); bool getFrameAnimPointCoords( unsigned anim, unsigned frame, unsigned point, double & x, double & y, double & z ) const; bool setFrameAnimPointRotation( unsigned anim, unsigned frame, unsigned point, double x, double y, double z ); bool getFrameAnimPointRotation( unsigned anim, unsigned frame, unsigned point, double & x, double & y, double & z ) const; // Skeletal animation keyframs int setSkelAnimKeyframe( unsigned anim, unsigned frame, unsigned joint, bool isRotation, double x, double y, double z ); bool getSkelAnimKeyframe( unsigned anim, unsigned frame, unsigned joint, bool isRotation, double & x, double & y, double & z ) const; bool hasSkelAnimKeyframe( unsigned anim, unsigned frame, unsigned joint, bool isRotation ) const; bool deleteSkelAnimKeyframe( unsigned anim, unsigned frame, unsigned joint, bool isRotation ); // Interpolate what a keyframe for this joint would be at the specified frame. bool interpSkelAnimKeyframe( unsigned anim, unsigned frame, bool loop, unsigned joint, bool isRotation, double & x, double & y, double & z ) const; // Interpolate what a keyframe for this joint would be at the specified time. bool interpSkelAnimKeyframeTime( unsigned anim, double frameTime, bool loop, unsigned joint, Matrix & relativeFinal ) const; // Animation set operations int copyAnimation( AnimationModeE mode, unsigned anim, const char * newName ); int splitAnimation( AnimationModeE mode, unsigned anim, const char * newName, unsigned frame ); bool joinAnimations( AnimationModeE mode, unsigned anim1, unsigned anim2 ); bool mergeAnimations( AnimationModeE mode, unsigned anim1, unsigned anim2 ); int convertAnimToFrame( AnimationModeE mode, unsigned anim1, const char * newName, unsigned frameCount ); bool moveAnimation( AnimationModeE mode, unsigned oldIndex, unsigned newIndex ); // For undo, don't call these directly bool insertSkelAnimKeyframe( unsigned anim, Keyframe * keyframe ); bool removeSkelAnimKeyframe( unsigned anim, unsigned frame, unsigned joint, bool isRotation, bool release = false ); // Merge all animations from model into this model. // For skeletal, skeletons must match bool mergeAnimations( Model * model ); // When a model has frame animations, adding or removing primitives is disabled // (because of the large amount of undo information that would have to be stored). // Use this function to force an add or remove (you must make sure that you adjust // the frame animations appropriately as well as preventing an undo on the // operation you are performing). // // In other words, setting this to true is probably a really bad idea unless // you know what you're doing. void forceAddOrDelete( bool o ); bool canAddOrDelete() const { return (m_frameAnims.size() == 0 || m_forceAddOrDelete); }; // Show an error because the user tried to add or remove primitives while // the model has frame animations. void displayFrameAnimPrimitiveError(); int getNumFrames() const; // Deprecated // ------------------------------------------------------------------ // Normal functions // ------------------------------------------------------------------ bool getNormal( unsigned triangleNum, unsigned vertexIndex, float *normal ) const; bool getFlatNormal( unsigned triangleNum, float *normal ) const; float cosToPoint( unsigned triangleNum, double * point ) const; void calculateNormals(); void calculateSkelNormals(); void calculateFrameNormals( unsigned anim ); void invalidateNormals(); void invertNormals( unsigned triangleNum ); bool triangleFacesIn( unsigned triangleNum ); // ------------------------------------------------------------------ // Geometry functions // ------------------------------------------------------------------ inline int getVertexCount() const { return m_vertices.size(); } inline int getTriangleCount() const { return m_triangles.size(); } inline int getBoneJointCount() const { return m_joints.size(); } inline int getPointCount() const { return m_points.size(); } inline int getProjectionCount() const { return m_projections.size(); } bool getPositionCoords( const Position & pos, double * coord ) const; int addVertex( double x, double y, double z ); int addTriangle( unsigned vert1, unsigned vert2, unsigned vert3 ); void deleteVertex( unsigned vertex ); void deleteTriangle( unsigned triangle ); // No undo on this one void setVertexFree( unsigned v, bool o ); bool isVertexFree( unsigned v ) const; // When all faces attached to a vertex are deleted, the vertex is considered // an "orphan" and deleted (unless it is a "free" vertex, see m_free in the // vertex class). void deleteOrphanedVertices(); // A flattened triangle is a triangle with two or more corners that are // assigned to the same vertex (this usually happens when vertices are // welded together). void deleteFlattenedTriangles(); bool isTriangleMarked( unsigned t ) const; void subdivideSelectedTriangles(); void unsubdivideTriangles( unsigned t1, unsigned t2, unsigned t3, unsigned t4 ); // If co-planer triangles have edges with points that are co-linear they // can be combined into a single triangle. The simplifySelectedMesh function // performs this operation to combine all faces that do not add detail to // the model. void simplifySelectedMesh(); bool setTriangleVertices( unsigned triangleNum, unsigned vert1, unsigned vert2, unsigned vert3 ); bool getTriangleVertices( unsigned triangleNum, unsigned & vert1, unsigned & vert2, unsigned & vert3 ) const; void setTriangleMarked( unsigned triangleNum, bool marked ); void clearMarkedTriangles(); bool getVertexCoordsUnanimated( unsigned vertexNumber, double *coord ) const; bool getVertexCoords( unsigned vertexNumber, double *coord ) const; bool getVertexCoords2d( unsigned vertexNumber, ProjectionDirectionE dir, double *coord ) const; int getTriangleVertex( unsigned triangleNumber, unsigned vertexIndex ) const; void booleanOperation( BooleanOpE op, std::list & listA, std::list & listB ); Model * copySelected() const; // A BSP tree is calculated for triangles that have textures with an alpha // channel (transparency). It is used to determine in what order triangles // must be rendered to get the proper blending results (triangles that are // farther away from the camera are rendered first so that closer triangles // are drawn on top of them). void calculateBspTree(); void invalidateBspTree(); // The model argument should be const, but it calls setupJoints. // TODO: Calling setupJoints in here should not be necessary. bool mergeModels( Model * model, bool textures, AnimationMergeE mergeMode, bool emptyGroups, double * trans = NULL, double * rot = NULL ); // These are helper functions for the boolean operations void removeInternalTriangles( std::list & listA, std::list & listB ); void removeExternalTriangles( std::list & listA, std::list & listB ); void removeBTriangles( std::list & listA, std::list & listB ); // ------------------------------------------------------------------ // Group and material functions // ------------------------------------------------------------------ // TODO: Misnamed, should be getMaterialCount() inline int getTextureCount() const { return m_materials.size(); }; int addGroup( const char * name ); // Textures and Color materials go into the same material list int addTexture( Texture * tex ); int addColorMaterial( const char * name ); bool setGroupTextureId( unsigned groupNumber, int textureId ); void deleteGroup( unsigned group ); void deleteTexture( unsigned texture ); const char * getGroupName( unsigned groupNum ) const; bool setGroupName( unsigned groupNum, const char * groupName ); inline int getGroupCount() const { return m_groups.size(); }; int getGroupByName( const char * groupName, bool ignoreCase = false ) const; int getMaterialByName( const char * materialName, bool ignoreCase = false ) const; Material::MaterialTypeE getMaterialType( unsigned materialIndex ) const; int getMaterialColor( unsigned materialIndex, unsigned c, unsigned v = 0 ) const; // These implicitly change the material type. void setMaterialTexture( unsigned textureId, Texture * tex ); void removeMaterialTexture( unsigned textureId ); uint8_t getGroupSmooth( unsigned groupNum ) const; bool setGroupSmooth( unsigned groupNum, uint8_t smooth ); uint8_t getGroupAngle( unsigned groupNum ) const; bool setGroupAngle( unsigned groupNum, uint8_t angle ); void setTextureName( unsigned textureId, const char * name ); const char * getTextureName( unsigned textureId ) const; const char * getTextureFilename( unsigned textureId ) const; Texture * getTextureData( unsigned textureId ); const Texture * getTextureData( unsigned textureId ) const { return getTextureData( textureId ); } // Lighting accessors bool getTextureAmbient( unsigned textureId, float * ambient ) const; bool getTextureDiffuse( unsigned textureId, float * diffuse ) const; bool getTextureEmissive( unsigned textureId, float * emissive ) const; bool getTextureSpecular( unsigned textureId, float * specular ) const; bool getTextureShininess( unsigned textureId, float & shininess ) const; bool setTextureAmbient( unsigned textureId, const float * ambient ); bool setTextureDiffuse( unsigned textureId, const float * diffuse ); bool setTextureEmissive( unsigned textureId, const float * emissive ); bool setTextureSpecular( unsigned textureId, const float * specular ); bool setTextureShininess( unsigned textureId, float shininess ); // See the clamp property in the Material class. bool getTextureSClamp( unsigned textureId ) const; bool getTextureTClamp( unsigned textureId ) const; bool setTextureSClamp( unsigned textureId, bool clamp ); bool setTextureTClamp( unsigned textureId, bool clamp ); list getUngroupedTriangles() const; list getGroupTriangles( unsigned groupNumber ) const; int getGroupTextureId( unsigned groupNumber ) const; int getTriangleGroup( unsigned triangleNumber ) const; void addTriangleToGroup( unsigned groupNum, unsigned triangleNum ); void removeTriangleFromGroup( unsigned groupNum, unsigned triangleNum ); void setSelectedAsGroup( unsigned groupNum ); void addSelectedToGroup( unsigned groupNum ); bool getTextureCoords( unsigned triangleNumber, unsigned vertexIndex, float & s, float & t ) const; bool setTextureCoords( unsigned triangleNumber, unsigned vertexIndex, float s, float t ); // ------------------------------------------------------------------ // Skeletal structure and influence functions // ------------------------------------------------------------------ int addBoneJoint( const char * name, double x, double y, double z, double xrot, double yrot, double zrot, int parent = -1 ); void deleteBoneJoint( unsigned joint ); const char * getBoneJointName( unsigned joint ) const; int getBoneJointParent( unsigned joint ) const; bool getBoneJointCoords( unsigned jointNumber, double * coord ) const; bool getBoneJointFinalMatrix( unsigned jointNumber, Matrix & m ) const; bool getBoneJointAbsoluteMatrix( unsigned jointNumber, Matrix & m ) const; bool getBoneJointRelativeMatrix( unsigned jointNumber, Matrix & m ) const; bool getPointFinalMatrix( unsigned jointNumber, Matrix & m ) const; list getBoneJointVertices( int joint ) const; int getVertexBoneJoint( unsigned vertexNumber ) const; int getPointBoneJoint( unsigned point ) const; bool setPositionBoneJoint( const Position & pos, int joint ); bool setVertexBoneJoint( unsigned vertex, int joint ); bool setPointBoneJoint( unsigned point, int joint ); bool addPositionInfluence( const Position & pos, unsigned joint, InfluenceTypeE type, double weight ); bool addVertexInfluence( unsigned vertex, unsigned joint, InfluenceTypeE type, double weight ); bool addPointInfluence( unsigned point, unsigned joint, InfluenceTypeE type, double weight ); bool removePositionInfluence( const Position & pos, unsigned joint ); bool removeVertexInfluence( unsigned vertex, unsigned joint ); bool removePointInfluence( unsigned point, unsigned joint ); bool removeAllPositionInfluences( const Position & pos ); bool removeAllVertexInfluences( unsigned vertex ); bool removeAllPointInfluences( unsigned point ); bool getPositionInfluences( const Position & pos, InfluenceList & l ) const; bool getVertexInfluences( unsigned vertex, InfluenceList & l ) const; bool getPointInfluences( unsigned point, InfluenceList & l ) const; int getPrimaryPositionInfluence( const Position & pos ) const; int getPrimaryVertexInfluence( unsigned vertex ) const; int getPrimaryPointInfluence( unsigned point ) const; bool setPositionInfluenceType( const Position & pos, unsigned joint, InfluenceTypeE type ); bool setVertexInfluenceType( unsigned vertex, unsigned joint, InfluenceTypeE type ); bool setPointInfluenceType( unsigned point, unsigned joint, InfluenceTypeE type ); bool setPositionInfluenceWeight( const Position & pos, unsigned joint, double weight ); bool setVertexInfluenceWeight( unsigned vertex, unsigned joint, double weight ); bool setPointInfluenceWeight( unsigned point, unsigned joint, double weight ); bool autoSetPositionInfluences( const Position & pos, double sensitivity, bool selected ); bool autoSetVertexInfluences( unsigned vertex, double sensitivity, bool selected ); bool autoSetPointInfluences( unsigned point, double sensitivity, bool selected ); bool autoSetCoordInfluences( double * coord, double sensitivity, bool selected, std::list & infList ); bool setBoneJointName( unsigned joint, const char * name ); bool setBoneJointParent( unsigned joint, int parent = -1 ); bool setBoneJointRotation( unsigned j, const double * rot ); bool setBoneJointTranslation( unsigned j, const double * trans ); double calculatePositionInfluenceWeight( const Position & pos, unsigned joint ) const; double calculateVertexInfluenceWeight( unsigned vertex, unsigned joint ) const; double calculatePointInfluenceWeight( unsigned point, unsigned joint ) const; double calculateCoordInfluenceWeight( const double * coord, unsigned joint ) const; void calculateRemainderWeight( InfluenceList & list ) const; bool getBoneVector( unsigned joint, double * vec, const double * coord ) const; // No undo on this one bool relocateBoneJoint( unsigned j, double x, double y, double z ); // Call this when a bone joint is moved, rotated, added, or deleted to // recalculate the skeletal structure. void setupJoints(); // ------------------------------------------------------------------ // Point functions // ------------------------------------------------------------------ int addPoint( const char * name, double x, double y, double z, double xrot, double yrot, double zrot, int boneId = -1 ); void deletePoint( unsigned point ); int getPointByName( const char * name ) const; const char * getPointName( unsigned point ) const; bool setPointName( unsigned point, const char * name ); int getPointType( unsigned point ) const; bool setPointType( unsigned point, int type ); // TODO: Orientation and Rotation are used for different purposes. // If it's safe to remove one in favor of the other, that should be done. bool getPointCoords( unsigned pointNumber, double * coord ) const; bool getPointOrientation( unsigned pointNumber, double * rot ) const; bool getPointRotation( unsigned point, double * rot ) const; bool getPointTranslation( unsigned point, double * trans ) const; bool setPointRotation( unsigned point, const double * rot ); bool setPointTranslation( unsigned point, const double * trans ); // ------------------------------------------------------------------ // Texture projection functions // ------------------------------------------------------------------ int addProjection( const char * name, int type, double x, double y, double z ); void deleteProjection( unsigned proj ); const char * getProjectionName( unsigned proj ) const; void setProjectionScale( unsigned p, double scale ); double getProjectionScale( unsigned p ) const; bool setProjectionName( unsigned proj, const char * name ); bool setProjectionType( unsigned proj, int type ); int getProjectionType( unsigned proj ) const; bool setProjectionRotation( unsigned proj, int type ); int getProjectionRotation( unsigned proj ) const; bool getProjectionCoords( unsigned projNumber, double *coord ) const; bool setProjectionUp( unsigned projNumber, const double *coord ); bool setProjectionSeam( unsigned projNumber, const double *coord ); bool setProjectionRange( unsigned projNumber, double xmin, double ymin, double xmax, double ymax ); bool getProjectionUp( unsigned projNumber, double *coord ) const; bool getProjectionSeam( unsigned projNumber, double *coord ) const; bool getProjectionRange( unsigned projNumber, double & xmin, double & ymin, double & xmax, double & ymax ) const; void setTriangleProjection( unsigned triangleNum, int proj ); int getTriangleProjection( unsigned triangleNum ) const; void applyProjection( unsigned int proj ); // ------------------------------------------------------------------ // Undo/Redo functions // ------------------------------------------------------------------ bool setUndoEnabled( bool o ); // Indicates that a user-specified operation is complete. A single // "operation" may span many function calls and different types of // manipulations. void operationComplete( const char * opname = NULL ); // Clear undo list void clearUndo(); bool canUndo() const; bool canRedo() const; void undo(); void redo(); // If a manipulations have been performed, but not commited as a single // undo list, undo those operations (often used when the user clicks // a "Cancel" button to discard "unapplied" changes). void undoCurrent(); const char * getUndoOpName() const; const char * getRedoOpName() const; // The limits at which undo operations are removed from memory. void setUndoSizeLimit( unsigned sizeLimit ); void setUndoCountLimit( unsigned countLimit ); // These functions are for undo and features such as this. // Don't use them unless you are me. void insertVertex( unsigned index, Vertex * vertex ); void removeVertex( unsigned index ); void insertTriangle( unsigned index, Triangle * triangle ); void removeTriangle( unsigned index ); void insertGroup( unsigned index, Group * group ); void removeGroup( unsigned index ); void insertBoneJoint( unsigned index, Joint * joint ); void removeBoneJoint( unsigned index ); void insertInfluence( const Position & pos, unsigned index, const InfluenceT & influence ); void removeInfluence( const Position & pos, unsigned index ); void insertPoint( unsigned index, Point * point ); void removePoint( unsigned index ); void insertProjection( unsigned index, TextureProjection * proj ); void removeProjection( unsigned index ); void insertTexture( unsigned index, Material * material ); void removeTexture( unsigned index ); void insertFrameAnim( unsigned index, FrameAnim * anim ); void removeFrameAnim( unsigned index ); void insertSkelAnim( unsigned anim, SkelAnim * fa ); void removeSkelAnim( unsigned anim ); void insertFrameAnimFrame( unsigned anim, unsigned frame, FrameAnimData * data ); void removeFrameAnimFrame( unsigned anim, unsigned frame ); // ------------------------------------------------------------------ // Selection functions // ------------------------------------------------------------------ void setSelectionMode( SelectionModeE m ); inline SelectionModeE getSelectionMode() { return m_selectionMode; }; unsigned getSelectedVertexCount() const; unsigned getSelectedTriangleCount() const; unsigned getSelectedBoneJointCount() const; unsigned getSelectedPointCount() const; unsigned getSelectedProjectionCount() const; void getSelectedPositions( list & l ) const; void getSelectedVertices( list & l ) const; void getSelectedTriangles( list & l ) const; void getSelectedGroups( list & l ) const; void getSelectedBoneJoints( list & l ) const; void getSelectedPoints( list & l ) const; void getSelectedProjections( list & l ) const; bool unselectAll(); bool unselectAllVertices(); bool unselectAllTriangles(); bool unselectAllGroups(); bool unselectAllBoneJoints(); bool unselectAllPoints(); bool unselectAllProjections(); // A selection test is an additional condition you can attach to whether // or not an object in the selection volume should be selected. For example, // this is used to add a test for which way a triangle is facing so that // triangles not facing the camera can be excluded from the selection. // You can implement a selection test for any property that you can check // on the primitive. class SelectionTest { public: virtual ~SelectionTest() {}; virtual bool shouldSelect( void * element ) = 0; }; bool selectInVolumeMatrix( const Matrix & viewMat, double x1, double y1, double x2, double y2, SelectionTest * test = NULL ); bool unselectInVolumeMatrix( const Matrix & viewMat, double x1, double y1, double x2, double y2, SelectionTest * test = NULL ); bool getBoundingRegion( double *x1, double *y1, double *z1, double *x2, double *y2, double *z2 ) const; bool getSelectedBoundingRegion( double *x1, double *y1, double *z1, double *x2, double *y2, double *z2 ) const; void deleteSelected(); // When changing the selection state of a lot of primitives, a difference // list is used to track undo information. These calls indicate when the // undo information should start being tracked and when it should be // completed. void beginSelectionDifference(); void endSelectionDifference(); bool selectVertex( unsigned v ); bool unselectVertex( unsigned v ); bool isVertexSelected( unsigned v ) const; bool selectTriangle( unsigned t ); bool unselectTriangle( unsigned t ); bool isTriangleSelected( unsigned t ) const; bool selectGroup( unsigned g ); bool unselectGroup( unsigned g ); bool isGroupSelected( unsigned g ) const; bool selectBoneJoint( unsigned j ); bool unselectBoneJoint( unsigned j ); bool isBoneJointSelected( unsigned j ) const; bool selectPoint( unsigned p ); bool unselectPoint( unsigned p ); bool isPointSelected( unsigned p ) const; bool selectProjection( unsigned p ); bool unselectProjection( unsigned p ); bool isProjectionSelected( unsigned p ) const; // The behavior of this function changes based on the selection mode. bool invertSelection(); // Select all vertices that have the m_free property set and are not used // by any triangles (this can be used to clean up unused free vertices, // like a manual analog to the deleteOrphanedVertices() function). void selectFreeVertices(); // ------------------------------------------------------------------ // Hide functions // ------------------------------------------------------------------ bool hideSelected(); bool hideUnselected(); bool unhideAll(); bool isVertexVisible( unsigned v ) const; bool isTriangleVisible( unsigned t ) const; bool isGroupVisible( unsigned g ) const; bool isBoneJointVisible( unsigned j ) const; bool isPointVisible( unsigned p ) const; // Don't call these directly... use selection/hide selection bool hideVertex( unsigned ); bool unhideVertex( unsigned ); bool hideTriangle( unsigned ); bool unhideTriangle( unsigned ); bool hideJoint( unsigned ); bool unhideJoint( unsigned ); bool hidePoint( unsigned ); bool unhidePoint( unsigned ); // ------------------------------------------------------------------ // Transform functions // ------------------------------------------------------------------ bool movePosition( const Position & pos, double x, double y, double z ); bool moveVertex( unsigned v, double x, double y, double z ); bool moveBoneJoint( unsigned j, double x, double y, double z ); bool movePoint( unsigned p, double x, double y, double z ); bool moveProjection( unsigned p, double x, double y, double z ); void translateSelected( const Matrix & m ); void rotateSelected( const Matrix & m, double * point ); // Applies arbitrary matrix to primitives (selected or all based on scope). // Some matrices cannot be undone (consider a matrix that scales a dimension to 0). // If the matrix cannot be undone, set undoable to false (a matrix is undoable if // the determinant is not equal to zero). void applyMatrix( const Matrix & m, OperationScopeE scope, bool animations, bool undoable ); protected: // ================================================================== // Protected methods // ================================================================== // ------------------------------------------------------------------ // Texture context methods // ------------------------------------------------------------------ DrawingContext * getDrawingContext( ContextT context ); void deleteGlTextures( ContextT context ); // If any group is using material "id", set the group to having // no texture (used when materials are deleted). void noTexture( unsigned id ); // ------------------------------------------------------------------ // Book-keeping for add/delete undo // ------------------------------------------------------------------ void adjustVertexIndices( unsigned index, int count ); void adjustTriangleIndices( unsigned index, int count ); void adjustProjectionIndices( unsigned index, int count ); // ------------------------------------------------------------------ // Texture projections // ------------------------------------------------------------------ void applyCylinderProjection( unsigned int proj ); void applySphereProjection( unsigned int proj ); void applyPlaneProjection( unsigned int proj ); // ------------------------------------------------------------------ // Hiding/visibility // ------------------------------------------------------------------ void beginHideDifference(); void endHideDifference(); // When primitives of one type are hidden, other primitives may need to // be hidden at the same time. void hideVerticesFromTriangles(); void unhideVerticesFromTriangles(); void hideTrianglesFromVertices(); void unhideTrianglesFromVertices(); // ------------------------------------------------------------------ // Selection // ------------------------------------------------------------------ bool selectVerticesInVolumeMatrix( bool select, const Matrix & viewMat, double a1, double b1, double a2, double b2, SelectionTest * test = NULL ); bool selectTrianglesInVolumeMatrix( bool select, const Matrix & viewMat, double a1, double b1, double a2, double b2, bool connected, SelectionTest * test = NULL ); bool selectGroupsInVolumeMatrix( bool select, const Matrix & viewMat, double a1, double b1, double a2, double b2, SelectionTest * test = NULL ); bool selectBoneJointsInVolumeMatrix( bool select, const Matrix & viewMat, double a1, double b1, double a2, double b2, SelectionTest * test = NULL ); bool selectPointsInVolumeMatrix( bool select, const Matrix & viewMat, double a1, double b1, double a2, double b2, SelectionTest * test = NULL ); bool selectProjectionsInVolumeMatrix( bool select, const Matrix & viewMat, double a1, double b1, double a2, double b2, SelectionTest * test = NULL ); // When primitives of one type are selected, other primitives may need to // be selected at the same time. void selectTrianglesFromGroups(); void selectVerticesFromTriangles(); void selectTrianglesFromVertices( bool all = true ); void selectGroupsFromTriangles( bool all = true ); bool parentJointSelected( int joint ) const; bool directParentJointSelected( int joint ) const; // ------------------------------------------------------------------ // Undo // ------------------------------------------------------------------ void sendUndo( Undo * undo, bool listCombine = false ); // ------------------------------------------------------------------ // Meta // ------------------------------------------------------------------ void updateObservers(); // ------------------------------------------------------------------ // Protected data // ------------------------------------------------------------------ // See the various accessors for this data for details on what these // properties mean. bool m_initialized; std::string m_filename; std::string m_exportFile; std::string m_filterSpecificError; static std::string s_lastFilterError; std::list m_loadErrors; MetaDataList m_metaData; vector m_vertices; vector m_triangles; vector m_groups; vector m_materials; vector m_joints; vector m_points; vector m_projections; vector m_frameAnims; vector m_skelAnims; DrawingContextList m_drawingContexts; BspTree m_bspTree; bool m_validBspTree; vector m_formatData; int m_canvasDrawMode; DrawJointModeE m_drawJoints; bool m_drawProjections; bool m_validNormals; bool m_validJoints; bool m_forceAddOrDelete; int m_numFrames; // Deprecated AnimationModeE m_animationMode; bool m_animationLoop; unsigned m_currentFrame; unsigned m_currentAnim; double m_currentTime; #ifdef MM3D_EDIT ObserverList m_observers; BackgroundImage * m_background[6]; bool m_saved; SelectionModeE m_selectionMode; bool m_selecting; // What has changed since the last time the observers were notified? // See ChangeBits int m_changeBits; UndoManager * m_undoMgr; UndoManager * m_animUndoMgr; bool m_undoEnabled; #endif // MM3D_EDIT // Base position for skeletal animations (safe to ignore in MM3D). Matrix m_localMatrix; // ModelFilter is defined as a friend so that classes derived from ModelFilter // can get direct access to the model primitive lists (yes, it's a messy hack). friend class ModelFilter; }; extern void model_show_alloc_stats(); extern int model_free_primitives(); #endif //__MODEL_H mm3d-1.3.7/src/libmm3d/cobfilter.h0000644000175000017500000001717210744511346013560 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __COBFILTER_H #define __COBFILTER_H #include "modelfilter.h" #include #include #include #include #include #include class CobFilter : public ModelFilter { public: CobFilter(); virtual ~CobFilter(); Model::ModelErrorE readFile( Model * model, const char * const filename ); Model::ModelErrorE writeFile( Model * model, const char * const filename, ModelFilter::Options * o ); bool canRead( const char * filename ); bool canWrite( const char * filename ); bool canExport( const char * filename ); bool isSupported( const char * filename ); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); protected: enum _ChunkType_e { CT_Polygon, CT_Material, CT_Unknown, CT_EOF, CT_MAX }; typedef enum _ChunkType_e ChunkTypeE; enum _FaceFlags_e { FF_HOLE = 0x08, FF_BACKCULL = 0x10, }; struct _ChunkHeader_t { ChunkTypeE type; char chunkChars[5]; int majorVersion; int minorVersion; int chunkId; int parentId; size_t length; }; typedef struct _ChunkHeader_t ChunkHeaderT; struct _LocalAxes_t { float center[3]; float xAxis[3]; float yAxis[3]; float zAxis[3]; }; typedef struct _LocalAxes_t LocalAxesT; struct _Vertex_t { double coord[3]; }; typedef struct _Vertex_t VertexT; struct _TextureCoord_t { float u; float v; }; typedef struct _TextureCoord_t TextureCoordT; struct _PolygonVertex_t { int vertex; int uvCoord; }; typedef struct _PolygonVertex_t PolygonVertexT; struct _PolygonFace_t { int flags; int matNumber; std::vector< PolygonVertexT > faceVertices; }; typedef struct _PolygonFace_t PolygonFaceT; struct _CurrentPosition_t { // Note: translation is fourth column, not fourth row // Fourth matrix row is always 0,0,0,1 float mat[3][4]; void toMatrix( Matrix & m ) { m.loadIdentity(); for ( int r = 0; r < 4; r++ ) { for ( int c = 0; c < 3; c++ ) { m.set( r, c, mat[c][r] ); } } } }; typedef struct _CurrentPosition_t CurrentPositionT; struct _PolygonMesh_t { std::string name; LocalAxesT localAxes; CurrentPositionT currentPosition; std::vector< VertexT > vertexList; std::vector< TextureCoordT > uvList; std::vector< PolygonFaceT > faceList; }; typedef struct _PolygonMesh_t PolygonMeshT; struct _Material_t { int matNumber; int shaderType; int facetType; int facetAngle; float red; float blue; float green; float alpha; float ambient; float specular; float hilight; float refraction; std::string envFile; std::string texFile; std::string bumpFile; // Texture materials only float uOffset; float vOffset; float uRepeat; float vRepeat; // MM3D model data int materialId; }; typedef struct _Material_t MaterialT; struct _MeshMaterial_t { int meshChunkId; int matNumber; int groupId; }; typedef struct _MeshMaterial_t MeshMaterialT; static ChunkTypeE chunkCharsToType( const char * str ); MeshMaterialT * getMeshMaterial( int chunkId, int matNumber ); // Common read functions Model::ModelErrorE readFileHeader(); bool readMaterialChunk( const ChunkHeaderT & header ); bool readPolygonChunk( const ChunkHeaderT & header ); // Binary read functions int16_t readBShort(); int32_t readBLong(); float readBFloat(); char readBChar(); bool readBString( std::string & ); bool readBName( std::string & ); bool readBLocalAxes( LocalAxesT & ); bool readBCurrentPosition( CurrentPositionT & ); bool readBChunkHeader( ChunkHeaderT & ); bool readBPolygonChunk( const ChunkHeaderT & header, PolygonMeshT & mesh ); bool readBMaterialChunk( const ChunkHeaderT & header, MaterialT & material ); bool readBUnknownChunk( const ChunkHeaderT & header ); // ASCII read functions void skipASpace(); bool skipAString( const char * str ); int16_t readAShort(); int32_t readALong(); float readAFloat(); double readADouble(); char readAChar(); bool readAString( std::string & ); bool readAName( std::string & ); bool readALocalAxes( LocalAxesT & ); bool readACurrentPosition( CurrentPositionT & ); bool readAChunkHeader( ChunkHeaderT & ); bool readAPolygonChunk( const ChunkHeaderT & header, PolygonMeshT & mesh ); bool readAMaterialChunk( const ChunkHeaderT & header, MaterialT & material ); bool readAUnknownChunk( const ChunkHeaderT & header ); // Binary write functions void writeBShort( int16_t ); void writeBLong( int32_t ); void writeBFloat( float ); void writeBChar( char ); void writeBString( const std::string & ); void writeBName( const std::string & ); void writeBStandardAxes(); void writeBStandardPosition(); // Call this function to write the header void writeBChunkHeader( const ChunkHeaderT & header ); // Call this function after writing the chunk data to // correct the chunk size in the header void writeBChunkSize(); void writeBTriangleGroup( const std::list & triList, const std::string & name ); void writeBUngrouped(); void writeBGrouped(); void writeBMaterial( int32_t parentId, size_t materialNumber, int groupNumber ); void writeBDefaultMaterial( int32_t parentId ); void writeBEOF(); int32_t getNextChunkId(); Model * m_model; FILE * m_fp; uint8_t * m_bufPos; uint8_t * m_fileBuf; uint8_t * m_chunkStart; uint8_t * m_chunkEnd; size_t m_fileLength; size_t m_lastChunkSizeOffset; int32_t m_nextChunkId; bool m_isBinary; bool m_isLittleEndian; std::string m_modelPath; std::string m_modelBaseName; std::string m_modelFullName; std::vector m_meshMaterials; }; #endif // __COBFILTER_H mm3d-1.3.7/src/libmm3d/local_array.h0000644000175000017500000000326510744511346014075 00000000000000/* Misfit Model 3D * * Copyright (c) 2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __LOCAL_ARRAY_H #define __LOCAL_ARRAY_H #include template class local_array { public: local_array( T * pval = NULL ) : m_pval( pval ) {} ~local_array() { free_ptr(); } T * get() { return m_pval; } T * reset(T * newPval) { free_ptr(); return m_pval = newPval; } const T * get() const { return m_pval; } T & operator*() { return *m_pval; } T * operator->() { return m_pval; } const T & operator*() const { return *m_pval; } const T * operator->() const { return m_pval; } T * operator=(T* newPval) { return reset(newPval); } bool operator!() const { return m_pval == NULL; } bool isnull() const { return m_pval == NULL; } protected: void free_ptr() { delete[] m_pval; m_pval = NULL; } T * m_pval; }; #endif // __LOCAL_ARRAY_H mm3d-1.3.7/src/libmm3d/memdatasource.cc0000644000175000017500000000305410744511346014570 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "memdatasource.h" #include MemDataSource::MemDataSource( const uint8_t * buf, size_t bufSize ) : m_buf( buf ), m_bufSize( bufSize ) { if ( m_buf == NULL ) { setErrno( EBADF ); return; } setFileSize( bufSize ); } MemDataSource::~MemDataSource() { } bool MemDataSource::internalReadAt( off_t offset, const uint8_t ** buf, size_t * bufLen ) { // TODO should assert on buf and bufLen // If we had an error, just keep returning an error if ( errorOccurred() ) return false; if ( (size_t) offset > m_bufSize ) { setUnexpectedEof( true ); return false; } *buf = &m_buf[offset]; *bufLen = m_bufSize - offset; return true; } mm3d-1.3.7/src/libmm3d/model_copy.cc0000644000175000017500000002161710745042274014076 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "glmath.h" #include "log.h" #include "texmgr.h" #include #include using __gnu_cxx::hash_map; Model * Model::copySelected() const { Model * m = new Model; list tri; this->getSelectedTriangles( tri ); list joints; this->getSelectedBoneJoints( joints ); list points; this->getSelectedPoints( points ); list proj; this->getSelectedProjections( proj ); hash_map projMap; hash_map vertMap; hash_map triMap; hash_map jointMap; hash_map pointMap; list::iterator lit; if ( !proj.empty() ) { for ( lit = proj.begin(); lit != proj.end(); ++lit ) { const char * name = getProjectionName( *lit ); int type = getProjectionType( *lit ); double pos[3] = { 0, 0, 0 }; double up[3] = { 0, 0, 0 }; double seam[3] = { 0, 0, 0 }; double range[2][2] = { { 0, 0 }, { 0, 0 } }; getProjectionCoords( *lit, pos ); getProjectionUp( *lit, up ); getProjectionSeam( *lit, seam ); getProjectionRange( *lit, range[0][0], range[0][1], range[1][0], range[1][1] ); int np = m->addProjection( name, type, pos[0], pos[1], pos[2] ); m->setProjectionUp( np, up ); m->setProjectionSeam( np, seam ); m->setProjectionRange( np, range[0][0], range[0][1], range[1][0], range[1][1] ); m->selectProjection( np ); projMap[ *lit ] = np; } } if ( !tri.empty() ) { list vert; this->getSelectedVertices( vert ); // Copy vertices log_debug( "Copying %d vertices\n", vert.size() ); for ( lit = vert.begin(); lit != vert.end(); lit++ ) { double coords[3]; this->getVertexCoords( *lit, coords ); int nv = m->addVertex( coords[0], coords[1], coords[2] ); m->selectVertex( nv ); m->setVertexFree( nv, this->isVertexFree(*lit) ); vertMap[ *lit ] = nv; } // Copy faces log_debug( "Copying %d faces\n", tri.size() ); for ( lit = tri.begin(); lit != tri.end(); lit++ ) { unsigned v[3]; for ( int t = 0; t < 3; t++ ) { v[t] = this->getTriangleVertex( *lit, t ); } int nt = m->addTriangle( vertMap[v[0]] , vertMap[v[1]], vertMap[v[2]] ); m->selectTriangle( nt ); triMap[ *lit ] = nt; } // Copy texture coords log_debug( "Copying %d face texture coordinates\n", tri.size() ); for ( lit = tri.begin(); lit != tri.end(); lit++ ) { float s; float t; for ( unsigned i = 0; i < 3; i++ ) { this->getTextureCoords( (unsigned) *lit, i, s, t ); m->setTextureCoords( (unsigned) triMap[ *lit ], i, s, t ); } } // TODO only copy textures used by groups? // Copy textures // It's easier here to just copy the groups and textures // even if not needed, the user can delete the unecessary parts unsigned tcount = this->getTextureCount(); log_debug( "Copying %d textures\n", tcount ); for ( unsigned t = 0; t < tcount; t++ ) { switch ( this->getMaterialType( t ) ) { case Model::Material::MATTYPE_TEXTURE: { Texture * tex = TextureManager::getInstance()->getTexture( this->getTextureFilename( t ) ); m->addTexture( tex ); } break; default: log_error( "Unknown material type %d in duplicate\n", this->getMaterialType(t) ); case Model::Material::MATTYPE_BLANK: m->addColorMaterial( this->getTextureName( t ) ); break; } float c[4]; this->getTextureAmbient( t, c ); m->setTextureAmbient( t, c ); this->getTextureDiffuse( t, c ); m->setTextureDiffuse( t, c ); this->getTextureSpecular( t, c ); m->setTextureSpecular( t, c ); this->getTextureEmissive( t, c ); m->setTextureEmissive( t, c ); this->getTextureShininess( t, c[0] ); m->setTextureShininess( t, c[0] ); // TODO Material m_color (if ever used) m->setTextureSClamp( t, this->getTextureSClamp( t ) ); m->setTextureTClamp( t, this->getTextureTClamp( t ) ); } // TODO Only copy selected groups? // Copy groups // It's easier here to just copy the groups and textures // even if not needed, the user can delete the unecessary parts unsigned gcount = this->getGroupCount(); log_debug( "Copying %d groups\n", gcount ); for ( unsigned g = 0; g < gcount; g++ ) { m->addGroup( this->getGroupName( g ) ); m->setGroupSmooth( g, this->getGroupSmooth(g) ); m->setGroupAngle( g, this->getGroupAngle(g) ); m->setGroupTextureId( g, this->getGroupTextureId(g) ); } if ( gcount > 0 ) { // Set groups log_debug( "Setting %d triangle groups\n", tri.size() ); for ( lit = tri.begin(); lit != tri.end(); lit++ ) { // This works, even if triangle group == -1 int gid = this->getTriangleGroup(*lit); if ( gid >= 0 ) { m->addTriangleToGroup( gid, triMap[*lit] ); } } } } if ( !points.empty() ) { // Copy points log_debug( "Copying %d points\n", points.size() ); for ( lit = points.begin(); lit != points.end(); lit++ ) { double coord[3]; double rot[3] = { 0, 0, 0 }; this->getPointCoords( *lit, coord ); this->getPointRotation( *lit, rot ); // TODO point type (if it is ever used) int np = m->addPoint( this->getPointName( *lit ), coord[0], coord[1], coord[2], rot[0], rot[1], rot[2], -1 ); pointMap[ *lit ] = np; m->selectPoint( np ); } } if ( !joints.empty() ) { // Copy joints log_debug( "Copying %d joints\n", joints.size() ); for ( lit = joints.begin(); lit != joints.end(); lit++ ) { int parent = this->getBoneJointParent( *lit ); // TODO this will not work if parent joint comes after child // joint. That shouldn't happen... but... if ( this->isBoneJointSelected( parent ) ) { parent = jointMap[ parent ]; } else { if ( m->getBoneJointCount() > 0 ) parent = 0; else parent = -1; } double coord[3]; double rot[3] = { 0, 0, 0 }; this->getBoneJointCoords( *lit, coord ); int nj = m->addBoneJoint( this->getBoneJointName( *lit ), coord[0], coord[1], coord[2], rot[0], rot[1], rot[2], parent ); jointMap[ *lit ] = nj; m->selectBoneJoint( nj ); } for ( hash_map::iterator it = vertMap.begin(); it != vertMap.end(); ++it ) { InfluenceList il; getVertexInfluences( it->first, il ); for ( InfluenceList::iterator iit = il.begin(); iit != il.end(); ++iit ) { if ( isBoneJointSelected( iit->m_boneId ) ) { m->addVertexInfluence( it->second, jointMap[iit->m_boneId], iit->m_type, iit->m_weight ); } } } for ( hash_map::iterator it = pointMap.begin(); it != pointMap.end(); ++it ) { InfluenceList il; getPointInfluences( it->first, il ); for ( InfluenceList::iterator iit = il.begin(); iit != il.end(); ++iit ) { if ( isBoneJointSelected( iit->m_boneId ) ) { m->addPointInfluence( it->second, jointMap[iit->m_boneId], iit->m_type, iit->m_weight ); } } } } // TODO what about animations? m->invalidateNormals(); m->calculateNormals(); m->setupJoints(); return m; } mm3d-1.3.7/src/libmm3d/glmath.h0000644000175000017500000002006511025050654013047 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __GLMATH_H #define __GLMATH_H #include #include #include "mm3dtypes.h" const double PI = 3.1415926; const double PIOVER180 = PI / 180.0; class Vector; class Quaternion; class Matrix { public: Matrix(); ~Matrix() {}; void loadIdentity(); bool isIdentity() const; void show() const; void set( int r, int c, double val ) { m_val[ (r<<2) + c ] = val; } double get( int r, int c ) const { return m_val[ (r<<2) + c ]; } bool operator==( const Matrix & rhs ) const; bool equiv( const Matrix & rhs, double tolerance = 0.00001 ) const; void setTranslation( const Vector & vector ); void setTranslation( const double * vector ); void setTranslation( const double & x, const double & y, const double & z ); void setRotation( const Vector & radians ); void setRotation( const double * radians ); void setRotationInDegrees( const double * degrees ); void setRotationInDegrees( const Vector & degrees ); void setRotationInDegrees( double x, double y, double z ); void getRotation( double & x, double & y, double & z ) const; void getRotation( Vector & radians ) const; void getRotation( double * radians ) const; void getTranslation( double & x, double & y, double & z ) const; void getTranslation( Vector & vector ) const; void getTranslation( double * vector ) const; void setInverseRotation( const double * radians ); void setInverseRotationInDegrees( const double * radians ); void setRotationOnAxis( const double * pVect, double radians ); void setRotationQuaternion( const Quaternion & quat ); void getRotationQuaternion( Quaternion & quat ) const; void inverseTranslateVector( double * pVect ) const; void inverseRotateVector( double * pVect ) const; void normalizeRotation(); void apply( float * pVec ) const; void apply( double * pVec ) const; void apply( Vector & pVec ) const; void apply3( float * pVec ) const; void apply3( double * pVec ) const; void apply3( Vector & pVec ) const; void apply3x( float * pVec ) const; // Apply 4x4 matrix to 3 element vec void apply3x( double * pVec ) const; void apply3x( Vector & pVec ) const; void postMultiply( const Matrix & lhs ); float getDeterminant() const; float getDeterminant3() const; Matrix getInverse() const; void getSubMatrix( Matrix & ret, int i, int j ) const; friend Matrix operator*( const Matrix & lhs, const Matrix & rhs ); friend Vector operator*( const Vector & lhs, const Matrix & rhs ); friend class Vector; protected: const double * getMatrix() const { return m_val; }; double m_val[16]; }; class Vector { public: Vector( const double * val = NULL); Vector( const double & x, const double & y, const double & z, const double & w = 1.0 ); ~Vector(); void show() const; void translate( const Matrix & rhs ); void transform( const Matrix & rhs ); void transform3( const Matrix & rhs ); void set( int c, double val ); void setAll( double x, double y, double z, double w = 1.0 ); void setAll( const double * vec, int count = 3 ); double get( int c ) const { return m_val[c]; }; void scale( double val ); void scale3( double val ); double mag() const; double mag3() const; void normalize(); void normalize3(); double dot3( const Vector & rhs ) const; double dot4( const Vector & rhs ) const; Vector cross3( const Vector & rhs ) const; const double * getVector() const { return m_val; }; double * getVector() { return m_val; }; double & operator[]( int index ); const double & operator[]( int index ) const; Vector operator+=( const Vector & rhs ); Vector operator-=( const Vector & rhs ); bool operator==( const Vector & rhs ) const; friend Vector operator*( const Vector & lhs, const Matrix & rhs ); friend Vector operator*( const Vector & lhs, const double & rhs ); friend Vector operator-( const Vector & lhs, const Vector & rhs ); friend Vector operator+( const Vector & lhs, const Vector & rhs ); protected: double m_val[4]; }; class Quaternion : public Vector { public: Quaternion( const double * val = NULL ); Quaternion( const Vector & val ); ~Quaternion(); void show() const; void setEulerAngles( const double * radians ); void setRotationOnAxis( double x, double y, double z, double radians ); void setRotationOnAxis( const double * axis, double radians ); void setRotationToPoint( const double & faceX, const double & faceY, const double & faceZ, const double & pointX, const double & pointY, const double & pointZ ); void setRotationToPoint( const Vector & face, const Vector & point ); void getRotationOnAxis( double * axis, double & radians ) const; void set( int c, double val ); double get( int c ) const { return m_val[c]; }; void normalize(); Quaternion swapHandedness(); const double * getVector() const { return m_val; }; friend Quaternion operator*( const Quaternion & lhs, const Quaternion & rhs ); protected: //double m_val[4]; }; template bool float_equiv( T lhs, T rhs, double tolerance = 0.00001 ) { return ( fabs( lhs - rhs ) < tolerance ); } template bool floatCompareVector( const T * lhs, const T * rhs, size_t len, double tolerance = 0.00001 ) { for ( size_t index = 0; index < len; ++index ) if ( !float_equiv( lhs[index], rhs[index], tolerance ) ) return false; return true; } template T distance( T x1, T y1, T z1, T x2, T y2, T z2 ) { T xDiff = x1 - x2; T yDiff = y1 - y2; T zDiff = z1 - z2; return sqrt( xDiff*xDiff + yDiff*yDiff + zDiff*zDiff ); } template T distance( T x1, T y1, T x2, T y2 ) { T xDiff = x1 - x2; T yDiff = y1 - y2; return sqrt( xDiff*xDiff + yDiff*yDiff ); } template T mag3( const T * vec ) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2] ); } template void normalize3( T * vec ) { if ( vec != NULL ) { T length = mag3( vec ); vec[0] = vec[0] / length; vec[1] = vec[1] / length; vec[2] = vec[2] / length; } } extern double distance ( const Vector & v1, const Vector & v2 ); extern double distance ( const double * v1, const double * v2 ); template T dot3( const T * lhs, const T * rhs ) { return( lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2] ); } template bool equiv3( const T * lhs, const T * rhs ) { return( fabs(lhs[0] - rhs[0]) < 0.0001 && fabs(lhs[1] - rhs[1]) < 0.0001 && fabs(lhs[2] - rhs[2]) < 0.0001 ); } template static void calculate_normal( T * normal, const T * a, const T * b, const T * c ) { normal[0] = a[1] * (b[2] - c[2]) + b[1] * (c[2] - a[2]) + c[1] * (a[2] - b[2]); normal[1] = a[2] * (b[0] - c[0]) + b[2] * (c[0] - a[0]) + c[2] * (a[0] - b[0]); normal[2] = a[0] * (b[1] - c[1]) + b[0] * (c[1] - a[1]) + c[0] * (a[1] - b[1]); normalize3( normal ); } #endif // __GLMATH_H mm3d-1.3.7/src/libmm3d/model_bool.cc0000644000175000017500000006116610745042274014062 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "glmath.h" #include "log.h" #include "weld.h" #include const double TOLERANCE = 0.00005; const double ATOLERANCE = 0.00000001; static bool _coord_equiv( double * ac, double * bc ) { double d = distance( ac[0], ac[1], ac[2], bc[0], bc[1], bc[2] ); if ( d < TOLERANCE ) { return true; } else { return false; } } typedef struct _UnionTriangle_t { int tri; double norm[3]; unsigned int v[3]; double coord[3][3]; double center[3]; double tpoint[3]; double tnorm[3][3]; } UnionTriangleT; typedef std::list< UnionTriangleT > UnionTriangleList; typedef enum _IntersectionCheck_e { IC_TryAgain, // Swap A and B and try again IC_No, // No intersection found IC_Yes, // Intersection found IC_MAX } IntersectionCheckE; // This function returns the angle on pivot from point p1 to p2 static double _angleToPoint( double * pivot, double * p1, double * p2 ) { double vec1[3]; double vec2[3]; vec1[0] = p1[0] - pivot[0]; vec1[1] = p1[1] - pivot[1]; vec1[2] = p1[2] - pivot[2]; vec2[0] = p2[0] - pivot[0]; vec2[1] = p2[1] - pivot[1]; vec2[2] = p2[2] - pivot[2]; normalize3( vec1 ); normalize3( vec2 ); double d = dot3( vec1, vec2 ); if ( d > (1.0 - ATOLERANCE) ) { return 0.0; } else { return acos( d ); } } // returns: // 1 = in front // 0 = on plane // -1 = in back static int _pointInPlane( double * coord, double * triCoord, double * triNorm ) { double btoa[3]; for ( int j = 0; j < 3; j++ ) { btoa[j] = coord[j] - triCoord[j]; } normalize3( btoa ); double c = dot3( btoa, triNorm ); if ( c < -ATOLERANCE ) return -1; else if ( c > ATOLERANCE ) return 1; else return 0; } // returns: // 1 = inside triangle // 0 = on triangle edge // -1 = outside triangle static int _pointInTriangle( double * coord, UnionTriangleT & tri ) { int vside[3]; int i; for ( i = 0; i < 3; i++ ) { vside[i] = _pointInPlane( coord, tri.tpoint, tri.tnorm[i] ); } if ( vside[0] < 0 && vside[1] < 0 && vside[2] < 0 ) { return 1; } if ( vside[0] > 0 && vside[1] > 0 && vside[2] > 0 ) { return 1; } if ( vside[0] == 0 && vside[1] == vside[2] ) { return 0; } if ( vside[1] == 0 && vside[0] == vside[2] ) { return 0; } if ( vside[2] == 0 && vside[0] == vside[1] ) { return 0; } if ( vside[0] == 0 && vside[1] == 0 ) { return 0; } if ( vside[0] == 0 && vside[2] == 0 ) { return 0; } if ( vside[1] == 0 && vside[2] == 0 ) { return 0; } return -1; } // returns: // ipoint = coordinates of edge line and plane // bool = whether or not ipoint is between p1 and p2 static bool _findEdgePlaneIntersection( double * ipoint, double * p1, double * p2, double * triCoord, double * triNorm, bool checkRange = true ) { double edgeVec[3]; edgeVec[0] = p2[0] - p1[0]; edgeVec[1] = p2[1] - p1[1]; edgeVec[2] = p2[2] - p1[2]; /* log_debug( "finding intersection with plane with line from %f,%f,%f to %f,%f,%f\n", p1[0], p1[1], p1[2], p2[0], p2[1], p2[2] ); */ double a = dot3( edgeVec, triNorm ); double d = - dot3( triCoord, triNorm ); // prevent divide by zero if ( fabs(a) < TOLERANCE ) { // edge is parallel to plane, the value of ipoint is undefined return false; } // distance along edgeVec p1 to plane double dist = -(d + dot3( p1, triNorm )) / a; // dist is % of velocity vector, scale to get impact point edgeVec[0] *= dist; edgeVec[1] *= dist; edgeVec[2] *= dist; ipoint[0] = p1[0] + edgeVec[0]; ipoint[1] = p1[1] + edgeVec[1]; ipoint[2] = p1[2] + edgeVec[2]; if ( checkRange ) { // Make sure intersection point is between p1 and p2 if ( dist >= (0.0 - TOLERANCE) && dist <= (1.0 + TOLERANCE) ) { return true; } else { return false; } } else { // Distance is irrelevant, we just want to know where // the intersection is (as long as it's not behind the triangle) if ( dist >= (0.0 - TOLERANCE) ) { return true; } else { return false; } } } static void _initUnionTriangle( Model * model, UnionTriangleT & ut, int triIndex ) { ut.tri = triIndex; model->getTriangleVertices( triIndex, ut.v[0], ut.v[1], ut.v[2] ); int i; for ( i = 0; i < 3; i++ ) { model->getVertexCoords( ut.v[i], ut.coord[i] ); } calculate_normal( ut.norm, ut.coord[0], ut.coord[1], ut.coord[2] ); // Find center point and tent point (for inside-triangle test) for ( i = 0; i < 3; i++ ) { ut.center[i] = ( ut.coord[0][i] + ut.coord[1][i] + ut.coord[2][i] ) / 3.0; ut.tpoint[i] = ut.center[i] + ut.norm[i]; } // Find normals for tent triangles (for inside-triangle test) calculate_normal( ut.tnorm[0], ut.tpoint, ut.coord[0], ut.coord[1] ); calculate_normal( ut.tnorm[1], ut.tpoint, ut.coord[1], ut.coord[2] ); calculate_normal( ut.tnorm[2], ut.tpoint, ut.coord[2], ut.coord[0] ); } static bool _isValidTriangle( Model * model, int v1, int v2, int v3 ) { double coord[3][3]; model->getVertexCoords( v1, coord[0] ); model->getVertexCoords( v2, coord[1] ); model->getVertexCoords( v3, coord[2] ); if ( _coord_equiv( coord[0], coord[1] ) ) { return false; } if ( _coord_equiv( coord[0], coord[2] ) ) { return false; } if ( _coord_equiv( coord[1], coord[2] ) ) { return false; } double aval1; double aval2; double aval3; aval1 = fabs(_angleToPoint( coord[0], coord[1], coord[2] )); aval2 = fabs(_angleToPoint( coord[1], coord[0], coord[2] )); aval3 = fabs(_angleToPoint( coord[2], coord[0], coord[1] )); if ( aval1 < TOLERANCE && aval2 < TOLERANCE ) { return false; } if ( aval1 < TOLERANCE && aval3 < TOLERANCE) { return false; } if ( aval2 < TOLERANCE && aval3 < TOLERANCE) { return false; } return true; } typedef struct _NewTriangle_t { int v[3]; } NewTriangleT; typedef std::list< NewTriangleT > NewTriangleList; static void _cutTriangle( Model * model, UnionTriangleList & utl, UnionTriangleT & ut, UnionTriangleT & utCut, double * p1, double * p2 ) { log_debug( "cutting triangle %d\n", ut.tri ); int onVertex = 0; for ( int n = 0; n < 3; n++ ) { if ( _coord_equiv( ut.coord[n], p1 ) ) { onVertex++; } else if ( _coord_equiv( ut.coord[n], p2 ) ) { onVertex++; } } //log_debug( "onVertex = %d\n", onVertex ); double a1 = fabs( _angleToPoint( ut.coord[0], p1, ut.coord[1] ) ); double a2 = fabs( _angleToPoint( ut.coord[0], p2, ut.coord[1] ) ); if ( (a1 == 0 && a2 == 0) ) { // If we're a perfectly straight line from v0 to v1 then // our intersection line is on our edge. No need to cut. a1 = a2; return; } if ( _coord_equiv( ut.coord[0], p1 ) ) { a1 = 0.0; } if ( _coord_equiv( ut.coord[0], p2 ) ) { a2 = 0.0; } double nc1[3]; double nc2[3]; if ( a1 < a2 ) { nc1[0] = p1[0]; nc1[1] = p1[1]; nc1[2] = p1[2]; nc2[0] = p2[0]; nc2[1] = p2[1]; nc2[2] = p2[2]; } else { nc1[0] = p2[0]; nc1[1] = p2[1]; nc1[2] = p2[2]; nc2[0] = p1[0]; nc2[1] = p1[1]; nc2[2] = p1[2]; } double norm[3]; norm[0] = ut.norm[0]; norm[1] = ut.norm[1]; norm[2] = ut.norm[2]; int v1 = model->addVertex( nc1[0], nc1[1], nc1[2] ); int v2 = model->addVertex( nc2[0], nc2[1], nc2[2] ); NewTriangleT nt; NewTriangleList ntl; nt.v[0] = ut.v[0]; nt.v[1] = v1; nt.v[2] = v2; ntl.push_back( nt ); nt.v[0] = ut.v[0]; nt.v[1] = ut.v[1]; nt.v[2] = v1; ntl.push_back( nt ); nt.v[0] = ut.v[0]; nt.v[1] = v2; nt.v[2] = ut.v[2]; ntl.push_back( nt ); double newnorm[3] = {1,0,0}; calculate_normal( newnorm, ut.coord[2], nc2, nc1 ); if ( dot3( norm, newnorm ) > 0.0 ) { nt.v[0] = ut.v[2]; nt.v[1] = v2; nt.v[2] = v1; ntl.push_back( nt ); nt.v[0] = ut.v[2]; nt.v[1] = v1; nt.v[2] = ut.v[1]; ntl.push_back( nt ); } else { nt.v[0] = ut.v[1]; nt.v[1] = v2; nt.v[2] = v1; ntl.push_back( nt ); // reversed v[1] and v[2] (appears to behave correctly now) nt.v[0] = ut.v[2]; nt.v[1] = v2; nt.v[2] = ut.v[1]; ntl.push_back( nt ); } bool setUt = true; int group = model->getTriangleGroup( ut.tri ); // now add the remaining triangles to the list NewTriangleList::iterator it; for ( it = ntl.begin(); it != ntl.end(); it++ ) { if ( _isValidTriangle( model, (*it).v[0], (*it).v[1], (*it).v[2] ) ) { if ( setUt ) { setUt = false; model->setTriangleVertices( ut.tri, (*it).v[0], (*it).v[1], (*it).v[2] ); _initUnionTriangle( model, ut, ut.tri ); } else { int tri = model->addTriangle( (*it).v[0], (*it).v[1], (*it).v[2] ); if ( group >= 0 ) { model->addTriangleToGroup( group, tri ); } UnionTriangleT nut; _initUnionTriangle( model, nut, tri ); utl.push_back( nut ); } } } if ( setUt ) { log_error( "No valid triangles in any splits\n" ); } } static IntersectionCheckE _findIntersection( Model * model, UnionTriangleList & la, UnionTriangleList & lb, UnionTriangleT & a, UnionTriangleT & b ) { //log_debug( "checking %d against %d\n", a.tri, b.tri ); int i; int j; int sharedVertices = 0; int coPlanar = 0; int vside[3]; // on which side of B is each A vertex? /* for ( i = 0; i < 3; i++ ) { log_debug( " point %d: %f,%f,%f\n", a.tri, a.coord[i][0], a.coord[i][1], a.coord[i][2] ); } for ( i = 0; i < 3; i++ ) { log_debug( " point %d: %f,%f,%f\n", b.tri, b.coord[i][0], b.coord[i][1], b.coord[i][2] ); } */ bool inFront = false; bool inBack = false; for ( i = 0; i < 3; i++ ) { for ( j = 0; j < 3; j++ ) { // If the triangles share a vertex or if the vertices // are at the same point in space, they are considered "shared" if ( a.v[i] == b.v[j] || _coord_equiv( a.coord[i], b.coord[j] ) ) { sharedVertices++; } } } if ( sharedVertices == 3 ) { // triangles completely overlap each other // no splits required return IC_No; } // Calculate which side of B each A vertex is on for ( i = 0; i < 3; i++ ) { double btoa[3]; for ( j = 0; j < 3; j++ ) { btoa[j] = a.coord[i][j] - b.coord[i][j]; } normalize3( btoa ); double c = dot3( btoa, b.norm ); if ( c < -TOLERANCE ) { inBack = true; vside[i] = -1; } else if ( c > TOLERANCE ) { inFront = true; vside[i] = 1; } else { coPlanar++; vside[i] = 0; } } /* log_debug( " shared=%d coPlanar=%d front=%s back=%s\n", sharedVertices, coPlanar, (inFront ? "yes" : "no"), (inBack ? "yes" : "no") ); */ if ( sharedVertices == 2 && (inFront || inBack) ) { // triangles share an edge but are not co-planar // no splits required return IC_No; } // Are A and B co-planar? if ( coPlanar == 3 ) { // co-planar faces should only matter // if other non-coplanar faces intersect along the same edge (for face // removal purposes) // NOTE: My testing seems to confirm this, but there may be // cases where this is not true. If co-planar faces are not // getting split correctly this case may be the cause. // They are on the same plane but do not overlap // (but B may be inside A, swap and try again) //return IC_TryAgain; return IC_No; } // Does A go through B's plane? // (consider co-planar to go "through") if ( coPlanar == 2 || (inFront && inBack) ) { // Yes, does A go through B itself? int oddSide = 0; // default to 0, correct below int far1 = 1; int far2 = 2; if ( vside[1] != 0 && vside[1] != vside[0] && vside[1] != vside[2] ) { oddSide = 1; far1 = 0; far2 = 2; } else if ( vside[2] != 0 && vside[2] != vside[0] && vside[2] != vside[1] ) { oddSide = 2; far1 = 0; far2 = 1; } double ipoint1[3]; double ipoint2[3]; bool hit1 = _findEdgePlaneIntersection( ipoint1, a.coord[oddSide], a.coord[far1], b.coord[0], b.norm ); bool hit2 = _findEdgePlaneIntersection( ipoint2, a.coord[oddSide], a.coord[far2], b.coord[0], b.norm ); // hit1 and hit2 indicate that the edge crosses the plane // the follow up is to see if the intersection is within the triangle // On the triangle's edge counts as "inside" if ( hit1 ) { hit1 = (_pointInTriangle( ipoint1, b ) >= 0); //log_debug( " intersects plane at %f,%f,%f (%s)\n", ipoint1[0], ipoint1[1], ipoint1[2], (hit1 ? "yes" : "no") ); } if ( hit2 ) { hit2 = (_pointInTriangle( ipoint2, b ) >= 0 ); //log_debug( " intersects plane at %f,%f,%f (%s)\n", ipoint2[0], ipoint2[1], ipoint2[2], (hit2 ? "yes" : "no") ); } if ( hit1 || hit2 ) { // If the only intersection was on the plane's edge, // don't count it as an intersection if ( hit1 != hit2 ) { //log_debug( " one hit\n" ); if ( hit1 ) { //int i = _pointInTriangle( ipoint1, b ); //log_debug( " in triangle: %d\n", i ); if ( _pointInTriangle( ipoint1, b ) == 0 ) { // One intersection, on edge, bail return IC_TryAgain; } } if ( hit2 ) { //int i = _pointInTriangle( ipoint2, b ); //log_debug( " in triangle: %d\n", i ); if ( _pointInTriangle( ipoint2, b ) == 0 ) { // One intersection, on edge, bail return IC_TryAgain; } } } if ( hit1 && hit2 ) { _cutTriangle( model, la, a, b, ipoint1, ipoint2 ); _cutTriangle( model, lb, b, a, ipoint1, ipoint2 ); } else { // find point where edge leaves B and change ipoint to that point double epoint[3]; if ( !hit1 ) { for ( int i = 0; !hit1 && i < 3; i++ ) { hit1 = _findEdgePlaneIntersection( epoint, ipoint1, ipoint2, b.tpoint, b.tnorm[i] ); } memcpy( ipoint1, epoint, sizeof(epoint) ); } if ( !hit2 ) { for ( int i = 0; !hit2 && i < 3; i++ ) { hit2 = _findEdgePlaneIntersection( epoint, ipoint1, ipoint2, b.tpoint, b.tnorm[i] ); } memcpy( ipoint2, epoint, sizeof(epoint) ); } _cutTriangle( model, la, a, b, ipoint1, ipoint2 ); _cutTriangle( model, lb, b, a, ipoint1, ipoint2 ); } return IC_Yes; } // No, A edges go through B's plane, but not B itself, // but B edges may go through A, swap and try again return IC_TryAgain; } // No, A is entirely on one side of B's plane return IC_No; } static void _buildUnionTriangleList( Model * model, UnionTriangleList & buildList, std::list & sourceList ) { buildList.clear(); // Creation union triangle lists for intersection tests std::list::iterator it; for ( it = sourceList.begin(); it != sourceList.end(); it++ ) { UnionTriangleT ut; _initUnionTriangle( model, ut, *it ); buildList.push_back( ut ); } } static void _findNearTriangles( Model * model, UnionTriangleT & ut, UnionTriangleList & lb, int & coplanar, int & front ) { coplanar = -1; front = -1; double dist = 0.0; double ipoint[3]; UnionTriangleList::iterator it; UnionTriangleList::iterator save_it; for ( it = lb.begin(); it != lb.end(); it++ ) { if ( _findEdgePlaneIntersection( ipoint, ut.center, ut.tpoint, (*it).center, (*it).norm, false ) ) { //log_debug( "found line/plane intersection\n" ); if ( _pointInTriangle( ipoint, (*it) ) >= 0 ) { //log_debug( " intersection is in far triangle\n" ); if ( _pointInPlane( ipoint, ut.center, ut.norm ) == 0 ) { //log_debug( " intersection is in self (co planar)\n" ); coplanar = (*it).tri; } else { double d = mag3( ipoint ); if ( front < 0 || d < dist ) { //log_debug( " found new nearest front triangle\n" ); front = (*it).tri; dist = d; save_it = it; } } } } } if ( front >= 0 ) { if ( _pointInPlane( ut.center, (*save_it).center, (*save_it).norm ) > 0 ) { //log_debug( " front triangle faces us, we're outside\n" ); // our triangle is in front of an outward facing triangle, // so it is not inside another shape front = -1; } } } static void _removeInternalTriangles( Model * model, UnionTriangleList & la, UnionTriangleList & lb ) { std::list removeList; std::list removeList2; int coplanar; int front; UnionTriangleList::iterator it; for ( it = la.begin(); it != la.end(); it++ ) { _findNearTriangles( model, *it, lb, coplanar, front ); if ( front >= 0 ) { //log_debug( "A triangle %d is on the inside\n", (*it).tri ); removeList.push_back( (*it).tri ); } } for ( it = lb.begin(); it != lb.end(); it++ ) { _findNearTriangles( model, *it, la, coplanar, front ); if ( front >= 0 || coplanar >= 0 ) { //log_debug( "B triangle %d is on the inside\n", (*it).tri ); removeList2.push_back( (*it).tri ); } } // Must delete in reverse order because deleting a triangle invalidates // any index that comes after it. int a = -1; int b = -1; while ( !removeList.empty() || !removeList2.empty() ) { a = -1; b = -1; if ( !removeList.empty() ) { a = removeList.back(); } if ( !removeList2.empty() ) { b = removeList2.back(); } if ( a > b ) { model->deleteTriangle( a ); removeList.pop_back(); } else { model->deleteTriangle( b ); removeList2.pop_back(); } } model->deleteOrphanedVertices(); } static void _removeExternalTriangles( Model * model, UnionTriangleList & la, UnionTriangleList & lb ) { std::list removeList; std::list removeList2; int coplanar; int front; UnionTriangleList::iterator it; for ( it = la.begin(); it != la.end(); it++ ) { _findNearTriangles( model, *it, lb, coplanar, front ); if ( front < 0 ) { //log_debug( "A triangle %d is on the inside\n", (*it).tri ); removeList.push_back( (*it).tri ); } } for ( it = lb.begin(); it != lb.end(); it++ ) { _findNearTriangles( model, *it, la, coplanar, front ); if ( front < 0 || coplanar >= 0 ) { //log_debug( "B triangle %d is on the inside\n", (*it).tri ); removeList2.push_back( (*it).tri ); } } // Must delete in reverse order because deleting a triangle invalidates // any index that comes after it. int a = -1; int b = -1; while ( !removeList.empty() || !removeList2.empty() ) { a = -1; b = -1; if ( !removeList.empty() ) { a = removeList.back(); } if ( !removeList2.empty() ) { b = removeList2.back(); } if ( a > b ) { model->deleteTriangle( a ); removeList.pop_back(); } else { model->deleteTriangle( b ); removeList2.pop_back(); } } model->deleteOrphanedVertices(); } static void _removeSubtractionTriangles( Model * model, UnionTriangleList & la, UnionTriangleList & lb ) { std::list invertList; std::list removeList; std::list removeList2; int coplanar; int front; UnionTriangleList::iterator it; for ( it = lb.begin(); it != lb.end(); it++ ) { _findNearTriangles( model, *it, la, coplanar, front ); if ( coplanar >= 0 ) { removeList.push_back( (*it).tri ); } else { if ( front >= 0 ) { //log_debug( "B triangle %d is on the inside\n", (*it).tri ); invertList.push_back( (*it).tri ); } else { //log_debug( "B triangle %d is on the outside\n", (*it).tri ); removeList.push_back( (*it).tri ); } } } for ( it = la.begin(); it != la.end(); it++ ) { _findNearTriangles( model, *it, lb, coplanar, front ); if ( coplanar >= 0 && front < 0 || coplanar < 0 && front >= 0 ) { //log_debug( "A triangle %d is on the inside\n", (*it).tri ); removeList2.push_back( (*it).tri ); } } std::list::iterator iit; for ( iit = invertList.begin(); iit != invertList.end(); iit++ ) { model->invertNormals( *iit ); } // Must delete in reverse order because deleting a triangle invalidates // any index that comes after it. int a = -1; int b = -1; while ( !removeList.empty() || !removeList2.empty() ) { a = -1; b = -1; if ( !removeList.empty() ) { a = removeList.back(); } if ( !removeList2.empty() ) { b = removeList2.back(); } if ( a > b ) { model->deleteTriangle( a ); removeList.pop_back(); } else { model->deleteTriangle( b ); removeList2.pop_back(); } } model->deleteOrphanedVertices(); } void Model::booleanOperation( Model::BooleanOpE op, std::list & listA, std::list & listB ) { UnionTriangleList la; UnionTriangleList lb; _buildUnionTriangleList( this, la, listA ); _buildUnionTriangleList( this, lb, listB ); UnionTriangleList::iterator a; UnionTriangleList::iterator b; for ( a = la.begin(); a != la.end(); a++ ) { for ( b = lb.begin(); b != lb.end(); b++ ) { if ( IC_TryAgain == _findIntersection( this, la, lb, *a, *b ) ) { _findIntersection( this, lb, la, *b, *a ); } } } for ( a = la.begin(); a != la.end(); a++ ) { selectTriangle( (*a).tri ); } for ( b = lb.begin(); b != lb.end(); b++ ) { selectTriangle( (*b).tri ); } weldSelectedVertices( this ); switch ( op ) { case BO_UnionRemove: _removeInternalTriangles( this, la, lb ); break; case BO_Subtraction: _removeSubtractionTriangles( this, la, lb ); break; case BO_Intersection: _removeExternalTriangles( this, la, lb ); break; default: log_error( "Uknown boolean op: %d\n", op ); case BO_Union: break; } } mm3d-1.3.7/src/libmm3d/cal3dfilter.cc0000644000175000017500000022271611025050654014134 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ // Cal 3D notes: // // Main file may be .cal or .cfg // // The .cal file may be ascii text .ini style, or XML. The XML .cal file // format is not supported. // // Versions: // // Version numbers are decimal // // Binary version 700 = XML Version 900 or 1000 // // XML version 900: // File has a
element with version // XML version 1000: // No header, version is part of top-level tag // // Binary version 1200: // Animation has an extra flag field at the start that indicates if // the animation tracks are compressed, plus possibly compressed tracks. // FIXME things to test: // // Read compressed tracks (TEST) // Are .cal and .cfg different? Looks like mesh/animation keys // don't have names (mesh= instead of mesh_foo=) #include "cal3dfilter.h" #include "model.h" #include "texture.h" #include "log.h" #include "endianconfig.h" #include "misc.h" #include "filtermgr.h" #include "texmgr.h" #include "mesh.h" #include "modelstatus.h" #include "mm3dport.h" #include "translate.h" #include "datadest.h" #include "datasource.h" #include "file_closer.h" #include "local_array.h" #include "release_ptr.h" #include #include #include #include #include #ifdef WIN32 #include #else #include #endif // WIN32 #include #include using std::list; using std::string; #ifdef PLUGIN static Cal3dFilter * s_filter = NULL; #endif // PLUGIN // These values are decimal, not hexadecimal #define CAL3D_MIN_BVERSION 700 #define CAL3D_MAX_BVERSION 1200 #define CAL3D_MIN_XVERSION 900 #define CAL3D_MAX_XVERSION 1000 // Versions where formats changed. Files with versions equal to or later than // these may make use of newer features. #define CAL3D_COMP_ANIM_VERSION 1200 // Compressed animation tracks #define CAL3D_NO_XHEADER_VERSION 1000 // XML files without
tags (version goes in top-level tag) // File magic number values #define CAL3D_MAGIC_SIZE 4 #define CAL3D_MAGIC_MATERIAL "CRF\0" #define CAL3D_MAGIC_MESH "CMF\0" #define CAL3D_MAGIC_SKELETON "CSF\0" #define CAL3D_MAGIC_ANIMATION "CAF\0" // FIXME centralize this template class FunctionCaller { public: FunctionCaller( T * obj, void (T::*method)(void) ) { m_obj = obj; m_method = method; } ~FunctionCaller() { (m_obj->*m_method)(); } private: T * m_obj; void (T::*m_method)(void); }; const Model::AnimationModeE MODE = Model::ANIMMODE_SKELETAL; static char * _skipSpace( char * str ) { while ( isspace( str[0] ) ) { str++; } return str; } static bool isallowed( char ch ) { switch ( ch ) { case '_': case '-': case '.': case '+': return true; default: break; } return false; } static void _escapeCal3dName( std::string & name ) { size_t i = 0; while ( i < name.size() ) { if ( isspace( name[i] ) ) { name[i] = '_'; i++; } else if ( !isalnum( name[i] ) && !isallowed( name[i] ) ) { name.erase(i,1); } else { i++; } } } static void _escapeFileName( std::string & file ) { _escapeCal3dName( file ); // for now this is the same code } static void _strtolower( std::string & str ) { size_t i = 0; for ( i = 0; i < str.size(); i++ ) { str[i] = tolower( str[i] ); } } Cal3dFilter::Cal3dOptions::Cal3dOptions() : m_singleMeshFile( true ), m_xmlMatFile( true ) { } Cal3dFilter::Cal3dOptions::~Cal3dOptions() { } void Cal3dFilter::Cal3dOptions::setOptionsFromModel( Model * m ) { char value[32]; if ( m->getMetaData( "cal3d_single_mesh_file", value, sizeof(value) ) ) { // Non-zero, single mesh m_singleMeshFile = atoi(value) != 0; } if ( m->getMetaData( "cal3d_xml_material", value, sizeof(value) ) ) { // Non-zero, use XML format for material m_xmlMatFile = atoi(value) != 0; } } Cal3dFilter::Cal3dFilter() : m_model( NULL ), m_options( NULL ) { m_formats.push_back( "cal" ); m_formats.push_back( "cfg" ); } Cal3dFilter::~Cal3dFilter() { } Model::ModelErrorE Cal3dFilter::readFile( Model * model, const char * const filename ) { Model::ModelErrorE err = Model::ERROR_NONE; // Use these to determine what versions of files to write. m_maxBinaryVersion = CAL3D_MIN_BVERSION; m_maxXrfVersion = CAL3D_MIN_XVERSION; if ( (err = readFileToBuffer( filename, m_fileBuf, m_fileLength )) == Model::ERROR_NONE ) { local_array releaseBuf( m_fileBuf ); m_bufPos = m_fileBuf; m_modelPath = ""; m_modelBaseName = ""; m_modelFullName = ""; normalizePath( filename, m_modelFullName, m_modelPath, m_modelBaseName ); m_currentPath = m_modelPath; model->setFilename( m_modelFullName.c_str() ); m_model = model; // Read specified file based on magic if ( memcmp( m_fileBuf, CAL3D_MAGIC_SKELETON, CAL3D_MAGIC_SIZE ) == 0 ) { err = readSkeletonFile( m_fileBuf, m_fileLength ); } else if ( memcmp( m_fileBuf, CAL3D_MAGIC_ANIMATION, CAL3D_MAGIC_SIZE ) == 0 ) { err = readAnimationFile( m_fileBuf, m_fileLength ); } else if ( memcmp( m_fileBuf, CAL3D_MAGIC_MESH, CAL3D_MAGIC_SIZE ) == 0 ) { m_model->updateMetaData( "cal3d_single_mesh_file", "1" ); err = readMeshFile( m_fileBuf, m_fileLength ); } else if ( memcmp( m_fileBuf, CAL3D_MAGIC_MATERIAL, CAL3D_MAGIC_SIZE ) == 0 ) { err = readMaterialFile( m_fileBuf, m_fileLength ); } else if ( m_fileBuf[0] == '<' ) { // probably an XML file, we only support material files err = readXSubFile( m_fileBuf, m_fileLength ); } else { err = readCal3dFile( m_fileBuf, m_fileLength ); } m_model->setupJoints(); log_debug( "Cal3D Model:\n" ); log_debug( " vertices: %d\n", m_model->getVertexCount() ); log_debug( " faces: %d\n", m_model->getTriangleCount() ); log_debug( " groups: %d\n", m_model->getGroupCount() ); log_debug( " bones: %d\n", m_model->getBoneJointCount() ); log_debug( " materials: %d\n", m_model->getTextureCount() ); m_fileBuf = NULL; m_bufPos = NULL; } char version[32]; PORT_snprintf( version, sizeof(version), "%d", m_maxXrfVersion ); model->updateMetaData( "cal3d_xrf_version", version ); PORT_snprintf( version, sizeof(version), "%d", m_maxBinaryVersion ); model->updateMetaData( "cal3d_binary_version", version ); return err; } Model::ModelErrorE Cal3dFilter::writeFile( Model * model, const char * const filename, ModelFilter::Options * o ) { if ( filename == NULL || filename[0] == '\0' ) { return Model::ERROR_BAD_ARGUMENT; } m_modelPath = ""; m_modelBaseName = ""; m_modelFullName = ""; normalizePath( filename, m_modelFullName, m_modelPath, m_modelBaseName ); m_model = model; m_options = NULL; const char * ext = strrchr( filename, '.' ); if ( ext ) { ext++; if ( strcasecmp( ext, "CSF" ) == 0 ) { return writeSkeletonFile( filename, model ); } else if ( strcasecmp( ext, "CAF" ) == 0 ) { if ( model->getAnimCount( MODE ) > 0 ) { return writeAnimationFile( filename, model, 0 ); } return Model::ERROR_BAD_DATA; } else if ( strcasecmp( ext, "CMF" ) == 0 ) { return writeMeshFile( filename, model ); } else if ( strcasecmp( ext, "CRF" ) == 0 ) { if ( model->getTextureCount() > 0 ) { return writeMaterialFile( filename, model, 0 ); } return Model::ERROR_BAD_DATA; } else if ( strcasecmp( ext, "XRF" ) == 0 ) { if ( model->getTextureCount() > 0 ) { return writeXMaterialFile( filename, model, 0 ); } return Model::ERROR_BAD_DATA; } else if ( toupper(ext[0]) == 'X' ) { // Assume XML file return Model::ERROR_UNSUPPORTED_VERSION; } // Assume Cal3D master file return writeCal3dFile( filename, model, o ); } else { return writeCal3dFile( filename, model, o ); } } bool Cal3dFilter::canRead( const char * filename ) { log_debug( "canRead( %s )\n", filename ); log_debug( " true\n" ); return true; } bool Cal3dFilter::canWrite( const char * filename ) { log_debug( "canWrite( %s )\n", filename ); log_debug( " false\n" ); return false; } bool Cal3dFilter::canExport( const char * filename ) { log_debug( "canExport( %s )\n", filename ); log_debug( " true\n" ); return true; } bool Cal3dFilter::isSupported( const char * filename ) { log_debug( "isSupported( %s )\n", filename ); unsigned len = strlen(filename); for ( std::list::const_iterator it = m_formats.begin(); it != m_formats.end(); ++it ) { const std::string fmt = std::string(".") + *it; unsigned fmtlen = fmt.size(); if ( len >= fmtlen && strcasecmp( &filename[len-fmtlen], fmt.c_str() ) == 0 ) { log_debug( " true\n" ); return true; } } log_debug( " false\n" ); return false; } list< string > Cal3dFilter::getReadTypes() { list rval; for ( std::list::const_iterator it = m_formats.begin(); it != m_formats.end(); ++it ) { rval.push_back( std::string("*.") + *it ); } return rval; } list< string > Cal3dFilter::getWriteTypes() { list rval; for ( std::list::const_iterator it = m_formats.begin(); it != m_formats.end(); ++it ) { rval.push_back( std::string("*.") + *it ); } return rval; } //------------------------------------------------------------------ // Protected Methods //------------------------------------------------------------------ bool Cal3dFilter::listHas( const std::list & l, const std::string & val ) { std::list::const_iterator it = l.begin(); while ( it != l.end() ) { if ( (*it) == val ) { return true; } it++; } return false; } std::string Cal3dFilter::addExtension( const std::string file, const std::string ext ) { if ( file.size() > ext.size() ) { std::string cmp = std::string(".") + ext; size_t len = cmp.size() - file.size(); if ( strcasecmp( &(file.c_str()[file.size() - len]), ext.c_str() ) == 0 ) { return file; } } return file + std::string(".") + ext; } bool Cal3dFilter::versionIsValid( FileTypeE type, int version ) { if ( version >= CAL3D_MIN_BVERSION && version <= CAL3D_MAX_BVERSION ) { return true; } return false; } bool Cal3dFilter::xversionIsValid( FileTypeE type, int version ) { if ( version >= CAL3D_MIN_XVERSION && version <= CAL3D_MAX_XVERSION ) { return true; } return false; } //------------------------------------------------------------------ // Common read functions Model::ModelErrorE Cal3dFilter::readSubFile( const char * filename ) { Model::ModelErrorE err = Model::ERROR_NONE; std::string oldPath = m_currentPath; std::string fullPath = m_currentPath + std::string( "/" ) + filename; uint8_t * buf; size_t len; if ( (err = readFileToBuffer( fullPath.c_str(), buf, len )) == Model::ERROR_NONE ) { local_array releaseBuf(buf); std::string baseName; std::string fullName; normalizePath( fullPath.c_str(), fullName, m_currentPath, baseName ); const char * part = strrchr( filename, '/' ); if ( part ) { part++; } else { part = filename; } const char * ext = strrchr( filename, '.' ); if ( ext ) { m_modelPartName.assign( part, ext - part ); m_modelPartExt = &ext[1]; } else { m_modelPartName = part; } // Read specified file based on magic if ( memcmp( buf, CAL3D_MAGIC_SKELETON, CAL3D_MAGIC_SIZE ) == 0 ) { err = readSkeletonFile( buf, len ); } else if ( memcmp( buf, CAL3D_MAGIC_ANIMATION, CAL3D_MAGIC_SIZE ) == 0 ) { err = readAnimationFile( buf, len ); } else if ( memcmp( buf, CAL3D_MAGIC_MESH, CAL3D_MAGIC_SIZE ) == 0 ) { err = readMeshFile( buf, len ); } else if ( memcmp( buf, CAL3D_MAGIC_MATERIAL, CAL3D_MAGIC_SIZE ) == 0 ) { err = readMaterialFile( buf, len ); } else if ( buf[0] == '<' ) { // probably an XML file, try to parse it err = readXSubFile( buf, len ); } else { err = readCal3dFile( buf, len ); } m_currentPath = oldPath; } if ( err != Model::ERROR_NONE ) { std::string errStr = filename; errStr += ": "; errStr += Model::errorToString( err ); model_status( m_model, StatusError, STATUSTIME_LONG, errStr.c_str() ); } return err; } Model::ModelErrorE Cal3dFilter::readXSubFile( uint8_t * buf, size_t len ) { Model::ModelErrorE err = Model::ERROR_UNSUPPORTED_VERSION; uint8_t * oldFileBuf = m_fileBuf; uint8_t * oldBufPos = m_bufPos; size_t oldLen = m_fileLength; m_fileBuf = buf; m_bufPos = buf; m_fileLength = len; // Only support material XML files // Some versions of CAL3D files have a header element, some do not // If we see a HEADER element, get the MAGIC attribute if ( findXElement( "HEADER" ) ) { log_debug( "XML file has a
element\n" ); std::string magic = readXAttribute( "MAGIC" ); if ( strcmp( magic.c_str(), "XRF" ) == 0 ) { log_debug( "XML file is a material file\n" ); err = readXMaterialFile( buf, len ); } else { log_warning( "XML file is an unknown type: %s\n", magic.c_str() ); } } else if ( findXElement( "MATERIAL" ) ) { log_debug( "XML file does not have a header\n" ); log_debug( "XML file is a material file\n" ); err = readXMaterialFile( buf, len ); } else { log_debug( "Could not determine XML file type\n" ); log_warning( "XML file is an unsupported type (unrecognized root tag)\n" ); } m_fileBuf = oldFileBuf; m_bufPos = oldBufPos; m_fileLength = oldLen; return err; } Model::ModelErrorE Cal3dFilter::readCal3dFile( uint8_t * buf, size_t len ) { log_debug( "reading cal3d config file\n" ); Model::ModelErrorE rval = Model::ERROR_NONE; uint8_t * oldFileBuf = m_fileBuf; uint8_t * oldBufPos = m_bufPos; size_t oldLen = m_fileLength; m_fileBuf = buf; m_bufPos = buf; m_fileLength = len; string line = ""; string subfile = ""; // We start in the [model] section. Technically this is // incorrect, but it's an attempt to get around possible // bad files or bad parsing logic. This shouldn't hurt anything. // If there is a non-model section before the model section // it will be skipped. bool modelSection = true; // Save mesh, material, and animation files so we can // load them in our own preferred order. The only thing // we load as soon as we see it is the skeleton file. std::list< std::string > meshFiles; std::list< std::string > matFiles; std::list< std::string > animFiles; // If no usable data is found, the bracket count (ie, number of lines // that start with '<') is used to determine if the file was in XML format // so that we can give a more useful error message to the user. int bracketCount = 0; bool noData = true; while ( readBLine( line, len - (m_bufPos - m_fileBuf) ) ) { if ( modelSection ) { const char * str = _skipSpace( (char *) line.c_str() ); // only parse lines that are not empty or comments if ( str[0] && str[0] != '#' ) { if ( strncasecmp( str, "skeleton", 8 ) == 0 ) { noData = false; subfile = readLineFile( str ); if ( !subfile.empty() ) { log_debug( "loading skeleton file %s\n", subfile.c_str() ); readSubFile( subfile.c_str() ); } } else if ( strncasecmp( str, "mesh", 4 ) == 0 ) { noData = false; subfile = readLineFile( str ); if ( !subfile.empty() ) { meshFiles.push_back( subfile ); } } else if ( strncasecmp( str, "animation", 9 ) == 0 ) { noData = false; std::string animLabel = readLineKey( str ); subfile = readLineFile( str ); if ( !subfile.empty() && !animLabel.empty() ) { m_model->updateMetaData( animLabel.c_str(), subfile.c_str() ); if ( !listHas( animFiles, subfile ) ) { animFiles.push_back( subfile ); } } } else if ( strncasecmp( str, "material", 8 ) == 0 ) { noData = false; subfile = readLineFile( str ); if ( !subfile.empty() ) { matFiles.push_back( subfile ); } } else if ( strncasecmp( str, "path", 4 ) == 0 ) { noData = false; string value = readLineFile( str ); m_model->updateMetaData( "cal3d_path", value.c_str() ); } else if ( strncasecmp( str, "scale", 5 ) == 0 ) { noData = false; string value = readLineFile( str ); m_model->updateMetaData( "cal3d_scale", value.c_str() ); } else if ( strncasecmp( str, "rotate", 6 ) == 0 ) { noData = false; string value = readLineFile( str ); m_model->updateMetaData( "cal3d_rotate", value.c_str() ); } else if ( str[0] == '[' ) { // looks like a new section, see if it's a model section str++; while ( isspace( str[0] ) ) { str++; } if ( strncasecmp( str, "model", 5 ) == 0 ) { modelSection = true; } else { // Not a model section, skip it log_debug( "skipping [%s section\n", str ); modelSection = false; } } else if ( str[0] == '<' ) { ++bracketCount; } } if ( (m_bufPos - m_fileBuf) >= (int) m_fileLength ) { break; } } else { // Not in the model section, the only parsing we want // to do is to find the model section... const char * str = _skipSpace( (char *) line.c_str() ); if ( str[0] == '[' ) { // looks like a new section, see if it's a model section str++; while ( isspace( str[0] ) ) { str++; } if ( strncasecmp( str, "model", 5 ) == 0 ) { // Yes, it's a model section, enable the parsing logic log_debug( "entering model section\n" ); modelSection = true; } else { log_debug( "skipping [%s section\n", str ); modelSection = false; } } if ( (m_bufPos - m_fileBuf) >= (int) m_fileLength ) { break; } } } std::list< std::string >::iterator it; // If we didn't find any usable data, return an error. if ( noData ) { if ( bracketCount > 2 ) m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "MM3D does not support CAL3D files in XML format" ) ).c_str() ); else m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "The file does not contain any mesh or animation data" ) ).c_str() ); rval = Model::ERROR_FILTER_SPECIFIC; goto bail_out; } // Load materials first because meshes will reference them for ( it = matFiles.begin(); it != matFiles.end(); it++ ) { log_debug( "loading material file %s\n", (*it).c_str() ); readSubFile( (*it).c_str() ); } // Now load meshes for ( it = meshFiles.begin(); it != meshFiles.end(); it++ ) { log_debug( "loading mesh file %s\n", (*it).c_str() ); readSubFile( (*it).c_str() ); } m_model->updateMetaData( "cal3d_single_mesh_file", ( meshFiles.size() == 1 ) ? "1" : "0" ); // Now load animations for ( it = animFiles.begin(); it != animFiles.end(); it++ ) { log_debug( "loading animation file %s\n", (*it).c_str() ); readSubFile( (*it).c_str() ); } bail_out:; m_fileBuf = oldFileBuf; m_bufPos = oldBufPos; m_fileLength = oldLen; return rval; } Model::ModelErrorE Cal3dFilter::readSkeletonFile( uint8_t * buf, size_t len ) { uint8_t * oldFileBuf = m_fileBuf; uint8_t * oldBufPos = m_bufPos; size_t oldLen = m_fileLength; m_fileBuf = buf; m_bufPos = buf; m_fileLength = len; Model::ModelErrorE rval = Model::ERROR_NONE; if ( memcmp( CAL3D_MAGIC_SKELETON, m_bufPos, CAL3D_MAGIC_SIZE ) == 0 ) { m_bufPos += CAL3D_MAGIC_SIZE; int fileVersion = readBInt32(); int numBones = readBInt32(); if ( fileVersion > m_maxBinaryVersion ) m_maxBinaryVersion = fileVersion; log_debug( "skel version: %d (%x)\n", fileVersion, fileVersion ); bool success = true; if ( versionIsValid( FT_Skeleton, fileVersion ) ) { for ( int b = 0; success && b < numBones; b++ ) { success = readBBone(); } } else { rval = Model::ERROR_UNSUPPORTED_VERSION; log_error( "Unsupported CAL3D skeleton version %d\n", fileVersion ); } } else { rval = Model::ERROR_BAD_MAGIC; log_error( "Bad magic in skeleton file\n" ); } m_fileBuf = oldFileBuf; m_bufPos = oldBufPos; m_fileLength = oldLen; return rval; } Model::ModelErrorE Cal3dFilter::readMeshFile( uint8_t * buf, size_t len ) { uint8_t * oldFileBuf = m_fileBuf; uint8_t * oldBufPos = m_bufPos; size_t oldLen = m_fileLength; m_fileBuf = buf; m_bufPos = buf; m_fileLength = len; Model::ModelErrorE rval = Model::ERROR_NONE; if ( memcmp( CAL3D_MAGIC_MESH, m_bufPos, CAL3D_MAGIC_SIZE ) == 0 ) { m_bufPos += CAL3D_MAGIC_SIZE; int fileVersion = readBInt32(); int numSubMeshes = readBInt32(); if ( fileVersion > m_maxBinaryVersion ) m_maxBinaryVersion = fileVersion; log_debug( "mesh version: %d (%x)\n", fileVersion, fileVersion ); bool success = true; if ( versionIsValid( FT_Mesh, fileVersion ) ) { for ( int m = 0; success && m < numSubMeshes; m++ ) { success = readBSubMesh(); } } else { rval = Model::ERROR_UNSUPPORTED_VERSION; log_error( "Unsupported CAL3D mesh version %d\n", fileVersion ); } } else { rval = Model::ERROR_BAD_MAGIC; log_error( "Bad magic in mesh file\n" ); } m_fileBuf = oldFileBuf; m_bufPos = oldBufPos; m_fileLength = oldLen; return rval; } Model::ModelErrorE Cal3dFilter::readMaterialFile( uint8_t * buf, size_t len ) { uint8_t * oldFileBuf = m_fileBuf; uint8_t * oldBufPos = m_bufPos; size_t oldLen = m_fileLength; m_fileBuf = buf; m_bufPos = buf; m_fileLength = len; m_model->updateMetaData( "cal3d_xml_material", "0" ); Model::ModelErrorE rval = Model::ERROR_NONE; // We're going to add a material whether successful or not. Materials are // referenced by index so the material needs to exist even if it's not valid. Model::Material * mat = Model::Material::get(); mat->m_type = Model::Material::MATTYPE_BLANK; // assume mat->m_name = m_modelPartName; // this should be a sensible name mat->m_filename = ""; // none by default if ( memcmp( CAL3D_MAGIC_MATERIAL, m_bufPos, CAL3D_MAGIC_SIZE ) == 0 ) { m_bufPos += CAL3D_MAGIC_SIZE; int fileVersion = readBInt32(); if ( fileVersion > m_maxBinaryVersion ) m_maxBinaryVersion = fileVersion; log_debug( "mat version: %d (%x)\n", fileVersion, fileVersion ); if ( versionIsValid( FT_Material, fileVersion ) ) { Vector ambient; ambient[0] = ((float) readBUInt8()) / 255.0f; ambient[1] = ((float) readBUInt8()) / 255.0f; ambient[2] = ((float) readBUInt8()) / 255.0f; ambient[3] = ((float) readBUInt8()) / 255.0f; Vector diffuse; diffuse[0] = ((float) readBUInt8()) / 255.0f; diffuse[1] = ((float) readBUInt8()) / 255.0f; diffuse[2] = ((float) readBUInt8()) / 255.0f; diffuse[3] = ((float) readBUInt8()) / 255.0f; Vector specular; specular[0] = ((float) readBUInt8()) / 255.0f; specular[1] = ((float) readBUInt8()) / 255.0f; specular[2] = ((float) readBUInt8()) / 255.0f; specular[3] = ((float) readBUInt8()) / 255.0f; float shiny = readBFloat(); int numMaps = readBInt32(); if ( numMaps > 0 ) { // Texture-map, change type and add filename string filename; readBString( filename ); mat->m_type = Model::Material::MATTYPE_TEXTURE; mat->m_filename = normalizePath(filename.c_str(), m_currentPath.c_str()); // ignore everything else in the file } log_debug( "Reading material %d\n", m_model->getTextureCount() ); log_debug( " name %s\n", mat->m_name.c_str() ); log_debug( " num maps %d\n", numMaps ); log_debug( " file %s\n", mat->m_filename.c_str() ); log_debug( " diffuse %f,%f,%f\n", diffuse[0], diffuse[1], diffuse[2] ); log_debug( " ambient %f,%f,%f\n", ambient[0], ambient[1], ambient[2] ); log_debug( " specular %f,%f,%f\n", specular[0], specular[1], specular[2] ); log_debug( " shininess %f\n", shiny ); if ( numMaps > 1 ) { log_warning( " ignoring %d maps for %s\n", numMaps - 1, mat->m_name.c_str() ); } for ( int t = 0; t < 4; t++ ) { mat->m_diffuse[t] = diffuse[t]; mat->m_ambient[t] = ambient[t]; mat->m_specular[t] = specular[t]; mat->m_emissive[t] = 0.0f; } mat->m_shininess = shiny; } else { rval = Model::ERROR_UNSUPPORTED_VERSION; log_error( "Unsupported CAL3D material version %d\n", fileVersion ); } } else { rval = Model::ERROR_BAD_MAGIC; log_error( "Bad magic in material file\n" ); } getMaterialList( m_model ).push_back( mat ); m_fileBuf = oldFileBuf; m_bufPos = oldBufPos; m_fileLength = oldLen; return rval; } Model::ModelErrorE Cal3dFilter::readXMaterialFile( uint8_t * buf, size_t len ) { uint8_t * oldFileBuf = m_fileBuf; uint8_t * oldBufPos = m_bufPos; size_t oldLen = m_fileLength; m_fileBuf = buf; m_bufPos = buf; m_fileLength = len; m_model->updateMetaData( "cal3d_xml_material", "1" ); Model::ModelErrorE rval = Model::ERROR_NONE; // We're going to add a material whether successful or not. Materials are // referenced by index so the material needs to exist even if it's not valid. Model::Material * mat = Model::Material::get(); mat->m_type = Model::Material::MATTYPE_BLANK; // assume mat->m_name = m_modelPartName; // this should be a sensible name mat->m_filename = ""; // none by default if ( len > 0 ) { // don't worry about magic and version, just get to the material tag if ( findXElement( "MATERIAL" ) ) { std::string versionStr = readXAttribute( "VERSION" ); int xrfVersion = atoi( versionStr.c_str() ); if ( xrfVersion > m_maxXrfVersion ) m_maxXrfVersion = xrfVersion; Vector ambient( 0, 0, 0, 1 ); Vector diffuse( 1, 1, 1, 1 ); Vector specular( 0, 0, 0, 1 ); string matFile = ""; float shiny = 0.0f; if ( findXElement( "AMBIENT" ) ) { ambient = readAVector4( readXElement( "AMBIENT" ).c_str() ); ambient[0] /= 255.0; ambient[1] /= 255.0; ambient[2] /= 255.0; ambient[3] /= 255.0; } if ( findXElement( "DIFFUSE" ) ) { diffuse = readAVector4( readXElement( "DIFFUSE" ).c_str() ); diffuse[0] /= 255.0; diffuse[1] /= 255.0; diffuse[2] /= 255.0; diffuse[3] /= 255.0; } if ( findXElement( "SPECULAR" ) ) { specular = readAVector4( readXElement( "SPECULAR" ).c_str() ); specular[0] /= 255.0; specular[1] /= 255.0; specular[2] /= 255.0; specular[3] /= 255.0; } if ( findXElement( "SHININESS" ) ) { shiny = atof( readXElement( "SHININESS" ).c_str() ); } if ( findXElement( "MAP" ) ) { matFile = readAString( readXElement( "MAP" ).c_str() ); } if ( !matFile.empty() ) { mat->m_type = Model::Material::MATTYPE_TEXTURE; mat->m_filename = normalizePath(matFile.c_str(), m_currentPath.c_str()); } log_debug( "Reading material %d\n", m_model->getTextureCount() ); log_debug( " name %s\n", mat->m_name.c_str() ); log_debug( " file %s\n", mat->m_filename.c_str() ); log_debug( " diffuse %f,%f,%f\n", diffuse[0], diffuse[1], diffuse[2] ); log_debug( " ambient %f,%f,%f\n", ambient[0], ambient[1], ambient[2] ); log_debug( " specular %f,%f,%f\n", specular[0], specular[1], specular[2] ); log_debug( " shininess %f\n", shiny ); for ( int t = 0; t < 4; t++ ) { mat->m_diffuse[t] = diffuse[t]; mat->m_ambient[t] = ambient[t]; mat->m_specular[t] = specular[t]; mat->m_emissive[t] = 0.0f; } mat->m_shininess = shiny; } else { rval = Model::ERROR_BAD_MAGIC; log_error( "Could not find MATERIAL element in material file\n" ); } } else { rval = Model::ERROR_FILE_READ; log_error( "File is empty\n" ); } getMaterialList( m_model ).push_back( mat ); m_fileBuf = oldFileBuf; m_bufPos = oldBufPos; m_fileLength = oldLen; return rval; } Model::ModelErrorE Cal3dFilter::readAnimationFile( uint8_t * buf, size_t len ) { uint8_t * oldFileBuf = m_fileBuf; uint8_t * oldBufPos = m_bufPos; size_t oldLen = m_fileLength; m_fileBuf = buf; m_bufPos = buf; m_fileLength = len; Model::ModelErrorE rval = Model::ERROR_NONE; if ( memcmp( CAL3D_MAGIC_ANIMATION, m_bufPos, CAL3D_MAGIC_SIZE ) == 0 ) { m_bufPos += CAL3D_MAGIC_SIZE; int fileVersion = readBInt32(); float duration = readBFloat(); int numTracks = readBInt32(); if ( fileVersion > m_maxBinaryVersion ) m_maxBinaryVersion = fileVersion; log_debug( "anim version: %d (%x)\n", fileVersion, fileVersion ); if ( versionIsValid( FT_Animation, fileVersion ) ) { std::string name = m_modelPartName; bool compressed = false; if ( fileVersion >= CAL3D_COMP_ANIM_VERSION ) { int flags = readBInt32(); compressed = ( flags & 1 != 0 ); } //name += "."; //name += m_modelPartExt; //log_debug( " tracks: %d\n", numTracks ); //log_debug( " seconds: %f\n", duration ); // create animation // NOTE: assume 30 fps, may want to be smarter about this m_anim = m_model->addAnimation( MODE, name.c_str() ); m_model->setAnimFPS( MODE, m_anim, 30.0 ); m_model->setAnimFrameCount( MODE, m_anim, timeToFrame(duration, 30.0) + 1); bool success = true; for ( int t = 0; success && t < numTracks; t++ ) { if ( compressed ) success = readBCompressedAnimTrack( duration ); else success = readBAnimTrack(); } } else { rval = Model::ERROR_UNSUPPORTED_VERSION; log_error( "Unsupported CAL3D animation version %d\n", fileVersion ); } } else { rval = Model::ERROR_BAD_MAGIC; log_error( "Bad magic in mesh file\n" ); } m_fileBuf = oldFileBuf; m_bufPos = oldBufPos; m_fileLength = oldLen; return rval; } Model::ModelErrorE Cal3dFilter::readFileToBuffer( const char * filename, uint8_t * & buf, size_t & len ) { buf = NULL; len = 0; Model::ModelErrorE err = Model::ERROR_NONE; DataSource * src = openInput( filename, err ); FunctionCaller fc( src, &DataSource::close ); if ( err != Model::ERROR_NONE ) return err; len = src->getFileSize(); buf = new uint8_t[len]; src->readBytes( buf, len ); return err; } bool Cal3dFilter::readBBone() { log_debug( "Reading bone joint %d\n", m_model->getBoneJointCount() ); // Bone name std::string name; readBString( name ); log_debug( " name %s\n", name.c_str() ); // Bone position Vector trans = readBVector3(); Vector rotVec = readBVector4(); // Bone space translation Vector transLocal = readBVector3(); Vector rotQuatLocal = readBVector4(); log_debug( " pos = %.4f,%.4f,%.4f\n", trans[0], trans[1], trans[2] ); log_debug( " rot = %.4f,%.4f,%.4f,%.4f\n", rotVec[0], rotVec[1], rotVec[2], rotVec[3] ); log_debug( " lpos = %.4f,%.4f,%.4f\n", transLocal[0], transLocal[1], transLocal[2] ); log_debug( " lrot = %.4f,%.4f,%.4f,%.4f\n", rotQuatLocal[0], rotQuatLocal[1], rotQuatLocal[2], rotQuatLocal[3] ); // Parent bone joint int parent = readBInt32(); log_debug( " parent %d\n", parent ); // Children... we don't need this data, just skip past it int childCount = readBInt32(); //log_debug( " children %d\n", childCount ); for ( int c = 0; c < childCount; c++ ) { readBInt32(); } Quaternion rotQuat( rotVec ); Vector rot; // left-handed to right-handed conversion rotQuat = rotQuat.swapHandedness(); Matrix bmat; bmat.setRotationQuaternion( rotQuat ); bmat.setTranslation( trans ); // NOTE: This will not work if we're adding a joint with a parent // that is defined after us if ( parent >= 0 ) { if ( parent < m_model->getBoneJointCount() ) { Matrix pmat; m_model->getBoneJointAbsoluteMatrix( parent, pmat ); bmat = bmat * pmat; } else { log_error( " parent %d does not exist (yet)\n", parent ); } } //log_debug( " pre trans %f,%f,%f\n", // (float) trans[0], (float) trans[1], (float) trans[2] ); bmat.getTranslation( trans ); bmat.getRotation( rot ); //log_debug( " post trans %f,%f,%f\n", // (float) trans[0], (float) trans[1], (float) trans[2] ); /* log_debug( " rot %f,%f,%f\n", (float) rot[0], (float) rot[1], (float) rot[2] ); log_debug( " local trans %f,%f,%f\n", (float) transLocal[0], (float) transLocal[1], (float) transLocal[2] ); */ m_model->addBoneJoint( name.c_str(), trans[0], trans[1], trans[2], rot[0], rot[1], rot[2], parent ); return true; } bool Cal3dFilter::readBSubMesh() { log_debug( "Reading sub mesh %d\n", m_model->getGroupCount() ); int vertBase = m_model->getVertexCount(); int matId = readBInt32(); int numVerts = readBInt32(); int numFaces = readBInt32(); int numLOD = readBInt32(); int numSprings = readBInt32(); int numMaps = readBInt32(); string name = m_modelPartName; log_debug( " name: %s\n", name.c_str() ); log_debug( " material: %d\n", matId ); log_debug( " verts: %d\n", numVerts ); log_debug( " faces: %d\n", numFaces ); log_debug( " LOD steps: %d\n", numLOD ); log_debug( " springs: %d\n", numSprings ); log_debug( " maps: %d\n", numMaps ); if ( matId >= m_model->getTextureCount() ) { log_error( " material %d is out of range\n", matId ); } int group = m_model->addGroup( name.c_str() ); m_model->setGroupTextureId( group, matId ); UVList uvlist; // read vertices for ( int v = 0; v < numVerts; v++ ) { Vector pos = readBVector3(); readBVector3(); // normal, ignore it // LOD stuff, we ignore it readBInt32(); // vertex to collapse to readBInt32(); // number of faces collapsed // Add the vertex itself int vert = m_model->addVertex( pos[0], pos[1], pos[2] ); // Read UV for ( int m = 0; m < numMaps; m++ ) { float u = readBFloat(); float v = readBFloat(); // ignore unless it's the first one if ( m == 0 ) { // our vertices are per face, not per vertex // save this for faces section UVDataT uv; uv.u = u; uv.v = v; uvlist.push_back( uv ); } } // Read influences int numBones = readBInt32(); for ( int b = 0; b < numBones; b++ ) { int boneId = readBInt32(); float boneWeight = readBFloat(); if ( boneId < m_model->getBoneJointCount() ) { m_model->addVertexInfluence( vert, boneId, Model::IT_Custom, boneWeight ); } else { log_warning( " bone joint %d for vertex %d is out of range\n", boneId, vert ); } } if ( numSprings ) { // spring weight, only present if springs, ignore it readBFloat(); } } // read (and ignore) springs for ( int s = 0; s < numSprings; s++ ) { readBInt32(); // vertex 1 readBInt32(); // vertex 2 readBFloat(); // spring coefficient readBFloat(); // length of spring at rest (idle) } int vcount = m_model->getVertexCount(); int uvcount = uvlist.size(); // read faces for ( int f = 0; f < numFaces; f++ ) { int v1 = readBInt32(); int v2 = readBInt32(); int v3 = readBInt32(); if ( v1 < vcount && v2 < vcount && v3 < vcount ) { int tri = m_model->addTriangle( v1 + vertBase, v2 + vertBase, v3 + vertBase ); m_model->addTriangleToGroup( group, tri ); if ( v1 < uvcount && v2 < uvcount && v3 < uvcount ) { m_model->setTextureCoords( tri, 0, uvlist[v1].u, uvlist[v1].v ); m_model->setTextureCoords( tri, 1, uvlist[v2].u, uvlist[v2].v ); m_model->setTextureCoords( tri, 2, uvlist[v3].u, uvlist[v3].v ); } else { if ( uvcount > 0 ) { log_warning( "face vertex (%d,%d,%d) not in uvlist %d\n", v1, v2, v3, uvcount ); } } } else { log_error( "a vertex is out of range (%d,%d,%d) > %d\n", v1, v2, v3, vcount ); } } return true; } bool Cal3dFilter::readBAnimTrack() { //log_debug( "Reading animation track\n" ); int bone = readBInt32(); int numFrames = readBInt32(); //log_debug( " bone: %d\n", bone ); //log_debug( " frames: %d\n", numFrames ); for ( int f = 0; f < numFrames; f++ ) { float tsec = readBFloat(); // time in seconds Vector trans = readBVector3(); Vector rotVec = readBVector4(); Quaternion quat( rotVec ); quat = quat.swapHandedness(); Matrix m; m.setRotationQuaternion( quat ); m.setTranslation( trans ); // Cal3D anims are relative to joint parent // MM3D are relative to joint local position, convert Matrix inv; m_model->getBoneJointRelativeMatrix( bone, inv ); inv = inv.getInverse(); m = m * inv; double rot[3] = { 0, 0, 0 }; m.getRotation( rot ); m.getTranslation( trans ); int animFrame = timeToFrame( tsec, 30.0 ); m_model->setSkelAnimKeyframe( m_anim, animFrame, bone, true, rot[0], rot[1], rot[2] ); m_model->setSkelAnimKeyframe( m_anim, animFrame, bone, false, trans[0], trans[1], trans[2] ); } return true; } bool Cal3dFilter::readBCompressedAnimTrack( double duration ) { log_debug( "Reading animation track (compressed)\n" ); int bone = readBInt32(); int numFrames = readBInt32(); double scale[3] = { 1.0, 1.0, 1.0 }; double trans_min[3] = { 0.0, 0.0, 0.0 }; int comp_bits[3] = { 10, 11, 11 }; trans_min[0] = readBFloat(); trans_min[1] = readBFloat(); trans_min[2] = readBFloat(); scale[0] = readBFloat(); scale[1] = readBFloat(); scale[2] = readBFloat(); //log_debug( " bone: %d\n", bone ); //log_debug( " frames: %d\n", numFrames ); for ( int f = 0; f < numFrames; f++ ) { uint16_t qsec = readBInt16(); float tsec = (qsec / 65535.0) * duration; uint32_t trans_comp = readBInt32(); uint64_t rot_comp = readBUInt48(); log_debug( "compressed trans = %X rot = %llX\n", trans_comp, rot_comp ); Vector trans; Vector rotVec; for ( int i = 0; i < 3; ++i ) { trans[i] = ((2 << comp_bits[i]) - 1) & trans_comp; trans_comp = trans_comp >> comp_bits[i]; trans[i] /= (double) ((2 << comp_bits[i]) - 1); trans[i] *= scale[i]; } for ( int i = 0; i < 4; ++i ) { rotVec[i] = ((2 << 12) - 1) & rot_comp; rotVec[i] /= (double) ((2 << 12) - 1); rotVec[i] *= 2.0 - 1.0; } log_debug( "uncompressed quat = %f, %f, %f, %f \n", (float) rotVec[0], (float) rotVec[1], (float) rotVec[2], (float) rotVec[3] ); Quaternion quat( rotVec ); quat = quat.swapHandedness(); Matrix m; m.setRotationQuaternion( quat ); m.setTranslation( trans ); // Cal3D anims are relative to joint parent // MM3D are relative to joint local position, convert Matrix inv; m_model->getBoneJointRelativeMatrix( bone, inv ); inv = inv.getInverse(); m = m * inv; double rot[3] = { 0, 0, 0 }; m.getRotation( rot ); m.getTranslation( trans ); int animFrame = timeToFrame( tsec, 30.0 ); log_debug( "rotation (%f,%f,%f) translation (%f,%f,%f)\n", rot[0], rot[1], rot[2], trans[0], trans[1], trans[2] ); m_model->setSkelAnimKeyframe( m_anim, animFrame, bone, true, rot[0], rot[1], rot[2] ); m_model->setSkelAnimKeyframe( m_anim, animFrame, bone, false, trans[0], trans[1], trans[2] ); } return true; } uint64_t Cal3dFilter::readBUInt48() { uint32_t rval32 = readBInt32(); uint16_t rval16 = readBInt16(); uint64_t rval = ((uint64_t) rval16 << 32) | ((uint64_t) rval32); return rval; } int32_t Cal3dFilter::readBInt32() { int32_t rval = *((int32_t *) m_bufPos); m_bufPos += sizeof( rval ); rval = ltoh_u32( rval ); return rval; } int16_t Cal3dFilter::readBInt16() { int16_t rval = *((int16_t *) m_bufPos); m_bufPos += sizeof( rval ); rval = ltoh_u16( rval ); return rval; } uint8_t Cal3dFilter::readBUInt8() { uint8_t rval = *((uint8_t *) m_bufPos); m_bufPos += sizeof( rval ); return rval; } float Cal3dFilter::readBFloat() { float32_t rval = 0.0f; memcpy( &rval, m_bufPos, sizeof(rval ) ); m_bufPos += sizeof( rval ); rval = ltoh_float( rval ); return rval; } bool Cal3dFilter::readBString( std::string & str ) { size_t len = readBInt32(); size_t advance = len; while (len > 0 && m_bufPos[len-1] == '\0') --len; str.assign( (char *) m_bufPos, len ); //log_debug( "read string '%s' at %p\n", str.c_str(), m_bufPos ); m_bufPos += advance; return true; } bool Cal3dFilter::readBLine( std::string & str, size_t maxLen ) { size_t p = 0; size_t skipBytes = 0; for ( p = 0; p < maxLen; p++ ) { if ( m_bufPos[p] == '\n' ) { skipBytes = 1; break; } if ( m_bufPos[p] == '\r' && m_bufPos[p+1] == '\n' ) { skipBytes = 2; break; } } str.assign( (char *) m_bufPos, p ); m_bufPos += p + skipBytes; //log_debug( "size: %d, pos %d\n", maxLen, m_bufPos - m_fileBuf ); if ( (p + skipBytes) > 0 ) { return true; } else { return false; } } Vector Cal3dFilter::readBVector3() { Vector rval; rval[0] = readBFloat(); rval[1] = readBFloat(); rval[2] = readBFloat(); return rval; } Vector Cal3dFilter::readBVector4() { Vector rval; rval[0] = readBFloat(); rval[1] = readBFloat(); rval[2] = readBFloat(); rval[3] = readBFloat(); return rval; } Vector Cal3dFilter::readAVector3( const char * str ) { float fval[3]; sscanf( str, "%f %f %f", &fval[0], &fval[1], &fval[2] ); Vector rval; rval[0] = fval[0]; rval[1] = fval[1]; rval[2] = fval[2]; return rval; } Vector Cal3dFilter::readAVector4( const char * str ) { float fval[4]; sscanf( str, "%f %f %f %f", &fval[0], &fval[1], &fval[2], &fval[3] ); Vector rval; rval[0] = fval[0]; rval[1] = fval[1]; rval[2] = fval[2]; rval[3] = fval[3]; return rval; } std::string Cal3dFilter::readAString( const char * str ) { while ( isspace( str[0] ) ) { str++; } int len = strlen( str ) - 1; while ( len >= 0 && isspace( str[len] ) ) { len--; } len++; std::string rval; rval.assign( str, len ); return rval; } std::string Cal3dFilter::readLineFile( const char * str ) { const char * eq = strchr( str, '=' ); if ( eq ) { const char * start = strchr( eq, '"' ); if ( start ) { start += 1; const char * end = strchr( start, '"' ); if ( end ) { std::string rval; rval.assign( start, end - start ); return rval; } } else { // No quotes... uh... do... something eq++; // skip '=' while ( isspace( eq[0] ) ) { eq++; } return eq; } } return ""; } std::string Cal3dFilter::readLineKey( const char * str ) { const char * eq = strchr( str, '=' ); if ( eq ) { eq--; while (eq > str && isspace(*eq)) { eq--; } std::string rval; rval.assign( str, eq - str + 1 ); return rval; } return ""; } //------------------------------------------------------------------ // XML read functions // XXX: It is important to note that this XML reading functionality is // extremely limited. It is just barely good enough to read Cal3D // XML formats, and is not appropriate for any other uses. // // Why did I write my own instead of using a library? Primarily because // I don't want to increase external dependencies (mostly for portability // reasons). // // Why not use Qt's XML reading since MM3D is already using Qt? Because // the core MM3D model functionality is used in other projects that // do not link against Qt. // // So I wrote 3 XML parsing functions that are extremely limited use, // but "good enough" for what I need. // // Some things that are broken: // - No validity checks on input // - Can't ensure that an element is a sub-element (just looks at the // tags, not the document hierarchy) // - Attribute names must not be substrings of other attribute names // or attribute values in the same element (if there is you could // get a false attribute lookup) // - Text in an attribute value that looks like an element will be // parsed as an element // - It doesn't handle comments (elements in comments will be parsed) bool Cal3dFilter::findXElement( const char * tag ) { const char * buf = (const char *) m_fileBuf; size_t pos = m_bufPos - m_fileBuf; size_t tagLen = strlen( tag ); while ( pos < m_fileLength ) { if ( m_fileBuf[pos] == '<' ) { if ( strncasecmp( &buf[pos+1], tag, tagLen ) == 0) { m_bufPos = &m_fileBuf[pos]; //log_debug( "found tag %s at %p\n", tag, m_bufPos ); return true; } } pos++; } return false; } std::string Cal3dFilter::readXAttribute( const char * attr ) { const char * buf = (const char *) m_fileBuf; size_t pos = m_bufPos - m_fileBuf; size_t attrLen = strlen( attr ); size_t start = 0; bool inAttr = false; while ( pos < m_fileLength - 1 ) { if ( inAttr ) { if ( buf[pos] == '"' ) { std::string rval; rval.assign( &buf[ start ], pos - start ); //log_debug( "attribute: %s = %s\n", attr, rval.c_str() ); return rval; } } else { if ( strncmp( &buf[pos], attr, attrLen ) == 0 ) { pos += attrLen; while ( !inAttr && pos < m_fileLength - 1 ) { // NOTE: This assumes that no attribute name occures // as a sub-string of another attribute name or value. // It also assumes the '=' is present if ( buf[pos] == '"' ) { start = pos + 1; inAttr = true; // pos will get incremeneted at the end of the // outter loop to skip the quote char } else { pos++; } } } else if ( buf[pos] == '>' ) { return ""; } } pos++; } return ""; } std::string Cal3dFilter::readXElement( const char * tag ) { const char * buf = (const char *) m_fileBuf; size_t pos = m_bufPos - m_fileBuf; std::string endTag = std::string( "/" ) + tag; size_t tagLen = endTag.size(); bool inTag = true; size_t start = 0; while ( pos < m_fileLength - 1 ) { if ( inTag ) { if ( buf[pos] == '/' && buf[pos+1] == '>' ) { m_bufPos = &m_fileBuf[pos+2]; return ""; } else if ( buf[pos] == '>' ) { inTag = false; start = pos + 1; } } else { if ( buf[pos] == '<' ) { if ( strncasecmp( &buf[pos+1], endTag.c_str(), tagLen ) == 0) { m_bufPos = &m_fileBuf[pos]; //log_debug( "found end of tag %s at %p\n", tag, m_bufPos ); std::string rval; rval.assign( &buf[ start ], pos - start ); //log_debug( "tag data: %s\n", rval.c_str() ); return rval; } } } pos++; } return ""; } //------------------------------------------------------------------ // Format write functions Model::ModelErrorE Cal3dFilter::writeCal3dFile( const char * filename, Model * model, ModelFilter::Options * o ) { Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; std::string base = m_modelPath + "/"; // Use dynamic cast to determine if the object is of the proper type // If not, create new one that we will delete later. // // We need to create one to make sure that the default options we // use in the filter match the default options presented to the // user in the dialog box. m_options = dynamic_cast< Cal3dOptions *>( o ); release_ptr freeOptions = NULL; if ( !m_options ) { freeOptions = static_cast( getDefaultOptions() ); m_options = freeOptions.get(); } m_model->updateMetaData( "cal3d_single_mesh_file", m_options->m_singleMeshFile ? "1" : "0" ); m_model->updateMetaData( "cal3d_xml_material", m_options->m_xmlMatFile ? "1" : "0" ); m_dst->writeString( "#\n# cal3d model configuration file\n#\n" ); m_dst->writeString( "# File written by Misfit Model 3D\n" ); m_dst->writeString( "# http://www.misfitcode.com/misfitmodel3d/\n\n" ); m_dst->writeString( "[model]\n" ); char value[64]; if ( m_model->getMetaData( "cal3d_path", value, sizeof(value) ) ) { m_dst->writePrintf( "path=\"%s\"\n", value ); } if ( m_model->getMetaData( "cal3d_scale", value, sizeof(value) ) ) { m_dst->writePrintf( "scale=\"%s\"\n", value ); } if ( m_model->getMetaData( "cal3d_rotate", value, sizeof(value) ) ) { m_dst->writePrintf( "rotate=\"%s\"\n", value ); } m_dst->writeString( "\n# --- Skeleton ---\n" ); std::string skelFile = replaceExtension( m_modelBaseName.c_str(), "csf" ); m_dst->writePrintf( "skeleton = \"%s\"\n\n", skelFile.c_str() ); writeSkeletonFile( (base + skelFile).c_str(), model ); // To write animations: // // * Make a map of filenames written (case-sensitive) // and map of animations written. // // * Run through meta data and write file if not already // in map. // // * Run through animations. If any not written, write them // and create an animation line in the Cal3D file. typedef std::map AnimFileMap; AnimFileMap fileWritten; std::vector animWritten; animWritten.resize( model->getAnimCount( MODE ) ); m_dst->writePrintf( "# --- Animations ---\n" ); std::string animFile; char keyStr[PATH_MAX]; char valueStr[PATH_MAX]; unsigned int mtcount = model->getMetaDataCount(); for ( unsigned int mt = 0; mt < mtcount; mt++ ) { model->getMetaData( mt, keyStr, PATH_MAX, valueStr, PATH_MAX ); if ( strncmp(keyStr, "animation_", 10 ) == 0 ) { animFile = valueStr; std::string animName = removeExtension( valueStr ); int a = findAnimation( animName ); if ( a >= 0 && fileWritten.find(animFile) == fileWritten.end() ) { writeAnimationFile( (base + animFile).c_str(), model, a ); animWritten[a] = true; fileWritten[animFile] = true; } m_dst->writePrintf( "%s = \"%s\"\n", keyStr, animFile.c_str() ); } } unsigned int acount = model->getAnimCount( MODE ); for ( unsigned int a = 0; a < acount; a++ ) { if ( animWritten[a] == 0 ) { const char * animName = model->getAnimName( MODE, a ); animFile = animName; animFile = addExtension( animFile, "caf" ); m_dst->writePrintf( "animation_%s = \"%s\"\n", animName, animFile.c_str() ); writeAnimationFile( (base + animFile).c_str(), model, a ); animWritten[a] = 1; } } m_dst->writeString( "\n" ); // Create meshes split on groups, with UVs and // normals unique to each vertex MeshList ml; mesh_create_list( ml, model ); m_dst->writeString( "# --- Meshes ---\n" ); if ( (m_options == NULL) || m_options->m_singleMeshFile ) { std::string meshFile = replaceExtension( m_modelBaseName.c_str(), "cmf" ); m_dst->writePrintf( "mesh_file = \"%s\"\n", meshFile.c_str() ); writeMeshListFile( (base + meshFile).c_str(), model, ml ); } else { std::string meshName; std::string meshFile; unsigned int meshCount = ml.size(); unsigned int meshNum; typedef std::map FileMeshMap; FileMeshMap fmm; string groupName; for ( meshNum = 0; meshNum < meshCount; meshNum++ ) { groupName = m_model->getGroupName(ml[meshNum].group); _strtolower( groupName ); fmm[ groupName ].push_back( ml[meshNum] ); } // Write the meshes for each group for ( FileMeshMap::const_iterator fmm_it = fmm.begin(); fmm_it != fmm.end(); fmm_it++ ) { // Get a count of how many meshes make up this group // (probably 1, but you never know) string groupName = fmm_it->first; const MeshList & groupMeshList = fmm_it->second; // Create mesh name and filename strings string meshName = groupName; string meshFile = groupName + ".cmf"; _escapeCal3dName(meshName); _escapeFileName(meshFile); // Write mesh file m_dst->writePrintf( "mesh_%s = \"%s\"\n", meshName.c_str(), meshFile.c_str() ); writeMeshListFile( (base + meshFile).c_str(), model, groupMeshList ); } } m_dst->writeString( "\n# --- Materials ---\n" ); std::string matFile; unsigned int mcount = model->getTextureCount(); for ( unsigned int m = 0; m < mcount; m++ ) { const char * matName = model->getTextureName( m ); matFile = matName; if ( m_options && !m_options->m_xmlMatFile ) { matFile += ".crf"; writeMaterialFile( (base + matFile).c_str(), model, m ); } else { matFile += ".xrf"; writeXMaterialFile( (base + matFile).c_str(), model, m ); } m_dst->writePrintf( "material_%s = \"%s\"\n", matName, matFile.c_str() ); } m_dst->writeString( "\n" ); m_options = NULL; return err; } Model::ModelErrorE Cal3dFilter::writeXMaterialFile( const char * filename, Model * model, unsigned int materialId ) { DataDest * oldDst = m_dst; Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; // Header int version = CAL3D_MIN_XVERSION; char versionStr[32]; if ( model->getMetaData( "cal3d_xrf_version", versionStr, sizeof(versionStr) ) ) { version = atoi(versionStr); } if ( version < CAL3D_NO_XHEADER_VERSION ) m_dst->writePrintf( "
\n", version ); Model::Material::MaterialTypeE type = model->getMaterialType( materialId ); // Start material element m_dst->writePrintf( "= CAL3D_NO_XHEADER_VERSION ) m_dst->writePrintf( " VERSION=\"%d\"", version ); m_dst->writePrintf( ">\n" ); // Material lighting properties float fval[4]; model->getTextureAmbient( materialId, fval ); writeXColor( "AMBIENT", fval ); model->getTextureDiffuse( materialId, fval ); writeXColor( "DIFFUSE", fval ); model->getTextureSpecular( materialId, fval ); writeXColor( "SPECULAR", fval ); model->getTextureShininess( materialId, fval[0] ); m_dst->writePrintf( " %f\n", fval[0] ); // Texture map if ( type == Model::Material::MATTYPE_TEXTURE ) { std::string textureFile = model->getTextureFilename( materialId ); std::string fullName; std::string fullPath; std::string baseName; normalizePath( filename, fullName, fullPath, baseName ); std::string relativeFile = getRelativePath( fullPath.c_str(), textureFile.c_str() ); m_dst->writePrintf( " %s\n", relativeFile.c_str() ); } // close material element m_dst->writePrintf( "\n" ); m_dst = oldDst; return err; } Model::ModelErrorE Cal3dFilter::writeSkeletonFile( const char * filename, Model * model ) { DataDest * oldDst = m_dst; Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; unsigned int bcount = model->getBoneJointCount(); int32_t version = CAL3D_MIN_BVERSION; char versionStr[32]; if ( model->getMetaData( "cal3d_binary_version", versionStr, sizeof(versionStr) ) ) { version = atoi(versionStr); } // Header m_dst->writeBytes( (uint8_t *) CAL3D_MAGIC_SKELETON, CAL3D_MAGIC_SIZE ); m_dst->write( version ); m_dst->write( (int32_t) bcount ); for ( unsigned int b = 0; b < bcount; b++ ) { writeBBone( b ); } m_dst = oldDst; return err; } Model::ModelErrorE Cal3dFilter::writeMeshFile( const char * filename, Model * model ) { // Create a list of all meshes MeshList ml; mesh_create_list( ml, model ); return writeMeshListFile( filename, model, ml ); } Model::ModelErrorE Cal3dFilter::writeMeshListFile( const char * filename, Model * model, const MeshList & meshList ) { DataDest * oldDst = m_dst; Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; int32_t version = CAL3D_MIN_BVERSION; char versionStr[32]; if ( model->getMetaData( "cal3d_binary_version", versionStr, sizeof(versionStr) ) ) { version = atoi(versionStr); } // Header m_dst->writeBytes( (uint8_t *) CAL3D_MAGIC_MESH, CAL3D_MAGIC_SIZE ); m_dst->write( version ); m_dst->write( (int32_t) meshList.size() ); // Save mesh to file log_debug( "writing mesh file %s\n", filename ); MeshList::const_iterator mit; for ( mit = meshList.begin(); mit != meshList.end(); mit++ ) { log_debug( " writing a mesh\n" ); writeBMesh( *mit ); } m_dst = oldDst; return err; } Model::ModelErrorE Cal3dFilter::writeMaterialFile( const char * filename, Model * model, unsigned int materialId ) { DataDest * oldDst = m_dst; Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; // Header m_dst->writeBytes( (uint8_t *) CAL3D_MAGIC_MATERIAL, CAL3D_MAGIC_SIZE ); int32_t version = CAL3D_MIN_BVERSION; char versionStr[32]; if ( model->getMetaData( "cal3d_binary_version", versionStr, sizeof(versionStr) ) ) { version = atoi(versionStr); } m_dst->write( version ); // Material lighting properties float fval[4]; model->getTextureAmbient( materialId, fval ); writeBColor( fval ); model->getTextureDiffuse( materialId, fval ); writeBColor( fval ); model->getTextureSpecular( materialId, fval ); writeBColor( fval ); model->getTextureShininess( materialId, fval[0] ); m_dst->write( (float32_t) fval[0] ); // Texture map if ( model->getMaterialType( materialId ) == Model::Material::MATTYPE_TEXTURE ) { m_dst->write( (int32_t) 1 ); std::string textureFile = model->getTextureFilename( materialId ); std::string fullName; std::string fullPath; std::string baseName; normalizePath( filename, fullName, fullPath, baseName ); std::string relativeFile = getRelativePath( fullPath.c_str(), textureFile.c_str() ); writeBString( relativeFile ); } else { m_dst->write( (int32_t) 0 ); } m_dst = oldDst; return err; } Model::ModelErrorE Cal3dFilter::writeAnimationFile( const char * filename, Model * model, unsigned int animationId ) { DataDest * oldDst = m_dst; Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; // get anim header info float fps = model->getAnimFPS( MODE, animationId ); unsigned int frameCount = model->getAnimFrameCount( MODE, animationId ); float32_t duration = (double) frameCount / fps; if ( frameCount > 0 ) { duration = ((double) frameCount - 1) / fps; } // build track list std::list tracks; bool found = false; double kf[3]; unsigned int bcount = model->getBoneJointCount(); for ( unsigned int b = 0; b < bcount; b++ ) { found = false; for ( unsigned int f = 0; !found && f < frameCount; f++ ) { if ( model->getSkelAnimKeyframe( animationId, f, b, false, kf[0], kf[1], kf[2] ) || model->getSkelAnimKeyframe( animationId, f, b, true, kf[0], kf[1], kf[2] ) ) { found = true; tracks.push_back( b ); } } } int32_t version = CAL3D_MIN_BVERSION; char versionStr[32]; if ( model->getMetaData( "cal3d_binary_version", versionStr, sizeof(versionStr) ) ) { version = atoi(versionStr); } // write header m_dst->writeBytes( (uint8_t *) CAL3D_MAGIC_ANIMATION, CAL3D_MAGIC_SIZE ); m_dst->write( version ); m_dst->write( duration ); m_dst->write( (int32_t) tracks.size() ); if ( version >= CAL3D_COMP_ANIM_VERSION ) { // Flags, no compression m_dst->write( (int32_t) 0 ); } // write tracks std::list::iterator it; for ( it = tracks.begin(); it != tracks.end(); it++ ) { writeBAnimTrack( animationId, *it ); } m_dst = oldDst; return err; } void Cal3dFilter::writeBBone( unsigned int b ) { std::string name = m_model->getBoneJointName( b ); writeBString( name ); Matrix m; m_model->getBoneJointAbsoluteMatrix( b, m ); Matrix pinv; int parent = m_model->getBoneJointParent( b ); if ( parent >= 0 ) { m_model->getBoneJointAbsoluteMatrix( parent, pinv ); pinv = pinv.getInverse(); } Matrix lm; lm = m * pinv; Vector trans; Quaternion rot; lm.getTranslation( trans ); lm.getRotationQuaternion( rot ); rot = rot.swapHandedness(); writeBVector3( trans ); // relative to parent writeBQuaternion( rot ); m = m.getInverse(); m.getTranslation( trans ); m.getRotationQuaternion( rot ); rot = rot.swapHandedness(); writeBVector3( trans ); // model space writeBQuaternion( rot ); // write parent m_dst->write( (int32_t) parent ); // find children std::list children; unsigned bcount = m_model->getBoneJointCount(); for ( unsigned int child = 0; child < bcount; child++ ) { int cparent = m_model->getBoneJointParent( child ); if ( (unsigned int) cparent == b ) { children.push_back( child ); } } // write children m_dst->write( (int32_t) children.size() ); std::list::iterator it; for ( it = children.begin(); it != children.end(); it++ ) { m_dst->write( (int32_t) *it ); } } void Cal3dFilter::writeBAnimTrack( unsigned int anim, unsigned int bone ) { float fps = m_model->getAnimFPS( MODE, anim ); unsigned int frameCount = m_model->getAnimFrameCount( MODE, anim ); std::list frames; double kf[3]; for ( unsigned int f = 0; f < frameCount; f++ ) { if ( m_model->getSkelAnimKeyframe( anim, f, bone, false, kf[0], kf[1], kf[2] ) || m_model->getSkelAnimKeyframe( anim, f, bone, true, kf[0], kf[1], kf[2] ) ) { frames.push_back( f ); } } // write track info m_dst->write( (int32_t) bone ); m_dst->write( (int32_t) frames.size() ); // write keyframe data std::list::iterator it; for ( it = frames.begin(); it != frames.end(); it++ ) { double frameTime = ((double) (*it)) / fps; m_dst->write( (float32_t) frameTime ); // MM3D allows one type of keyframe without the other, Cal3D requires // both rotation and translation for each keyframe. If we have one // and the other is missing, we must do interpolation here. Matrix m; m_model->interpSkelAnimKeyframeTime( anim, frameTime, true, bone, m ); Matrix rm; m_model->getBoneJointRelativeMatrix( bone, rm ); m = m * rm; Vector trans; Quaternion rot; m.getRotationQuaternion( rot ); m.getTranslation( trans ); rot = rot.swapHandedness(); writeBVector3( trans ); writeBQuaternion( rot ); } } void Cal3dFilter::writeBMesh( const Mesh & mesh ) { int materialId = -1; if ( mesh.group >= 0 ) { materialId = m_model->getGroupTextureId( mesh.group ); } m_dst->write( (int32_t) materialId ); m_dst->write( (int32_t) mesh.vertices.size() ); m_dst->write( (int32_t) mesh.faces.size() ); m_dst->write( (int32_t) 0 ); m_dst->write( (int32_t) 0 ); if ( materialId >= 0 ) { m_dst->write( (int32_t) 1 ); } else { m_dst->write( (int32_t) 0 ); } double coord[3]; Mesh::VertexList::const_iterator vit; for ( vit = mesh.vertices.begin(); vit != mesh.vertices.end(); vit++ ) { const Mesh::Vertex & mv = *vit; m_model->getVertexCoordsUnanimated( mv.v, coord ); m_dst->write( (float32_t) coord[0] ); m_dst->write( (float32_t) coord[1] ); m_dst->write( (float32_t) coord[2] ); m_dst->write( (float32_t) mv.norm[0] ); m_dst->write( (float32_t) mv.norm[1] ); m_dst->write( (float32_t) mv.norm[2] ); m_dst->write( (int32_t) -1 ); m_dst->write( (int32_t) 0 ); if ( materialId >= 0 ) { m_dst->write( (float32_t) mv.uv[0] ); m_dst->write( (float32_t) mv.uv[1] ); } Model::InfluenceList il; Model::InfluenceList::iterator it; m_model->getVertexInfluences( mv.v, il ); // Our weights don't always equal 100%, get total weigth so we can normalize double total = 0.0; for ( it = il.begin(); it != il.end(); it++ ) { total += it->m_weight; } // Don't allow negative weights, or divide by zero if ( total < 0.0005 ) { total = 1.0; } // Write out influence list m_dst->write( (int32_t) il.size() ); // number of influences for ( it = il.begin(); it != il.end(); it++ ) { m_dst->write( (int32_t) it->m_boneId ); // bone m_dst->write( (float32_t) (it->m_weight / total) ); // normalized weight } // No springs, don't need to write weight } // Write springs... we don't have any... don't write anything // Write faces Mesh::FaceList::const_iterator fit; for ( fit = mesh.faces.begin(); fit != mesh.faces.end(); fit++ ) { const Mesh::Face & mf = *fit; m_dst->write( (int32_t) mf.v[0] ); m_dst->write( (int32_t) mf.v[1] ); m_dst->write( (int32_t) mf.v[2] ); } } //------------------------------------------------------------------ // Binary write functions void Cal3dFilter::writeBVector3( const Vector & vec ) { m_dst->write( (float32_t) vec[0] ); m_dst->write( (float32_t) vec[1] ); m_dst->write( (float32_t) vec[2] ); } void Cal3dFilter::writeBQuaternion( const Quaternion & quat ) { m_dst->write( (float32_t) quat[0] ); m_dst->write( (float32_t) quat[1] ); m_dst->write( (float32_t) quat[2] ); m_dst->write( (float32_t) quat[3] ); } void Cal3dFilter::writeBString( const std::string & str ) { // Include NULL byte in write uint32_t len = str.size() + 1; m_dst->write( len ); m_dst->writeBytes( (uint8_t *) str.c_str(), len ); } void Cal3dFilter::writeBColor( const float * fval ) { uint32_t dval; for ( int i = 0; i < 4; i++ ) { dval = (uint32_t) (fval[i] * 255.0); if ( dval > 255 ) { dval = 255; } m_dst->write( (uint8_t) dval ); } } void Cal3dFilter::writeXColor( const char * tag, const float * fval ) { m_dst->writePrintf( " <%s>", tag ); uint32_t dval; for ( int i = 0; i < 4; i++ ) { dval = (uint32_t) (fval[i] * 255.0); if ( dval > 255 ) { dval = 255; } m_dst->writePrintf( "%d%s", dval, (i < 3) ? " " : "" ); } m_dst->writePrintf( "\n", tag ); } int Cal3dFilter::timeToFrame( double tsec, double fps ) { int frame = 0; while ( (frame / fps) < (tsec - 0.0005f) ) { frame++; } //log_debug( " time %f is frame %d\n", tsec, frame ); return frame; } int Cal3dFilter::findAnimation( const std::string& animName ) { int acount = m_model->getAnimCount( MODE ); for ( int a = 0; a < acount; a++ ) { if ( strcasecmp( animName.c_str(), m_model->getAnimName( MODE, a ) ) == 0 ) { return a; } } return -1; } #ifdef PLUGIN //------------------------------------------------------------------ // Plugin functions //------------------------------------------------------------------ extern "C" bool plugin_init() { if ( s_filter == NULL ) { s_filter = new Cal3dFilter(); FilterManager * texmgr = FilterManager::getInstance(); texmgr->registerFilter( s_filter ); } log_debug( "CAL3D model filter plugin initialized\n" ); return true; } // The filter manager will delete our registered filter. // We have no other cleanup to do extern "C" bool plugin_uninit() { s_filter = NULL; // FilterManager deletes filters log_debug( "CAL3D model filter plugin uninitialized\n" ); return true; } extern "C" const char * plugin_version() { return "0.1.0"; } extern "C" const char * plugin_desc() { return "CAL3D model filter"; } #endif // PLUGIN mm3d-1.3.7/src/libmm3d/datadest.h0000644000175000017500000001546311000471707013371 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef DATADEST_INC_H__ #define DATADEST_INC_H__ #include #include #include #include #include #include "mm3dtypes.h" #include "model.h" //----------------------------------------------------------------------------- // About DataDest //----------------------------------------------------------------------------- // // A DataDest is used as export output for model or texture file filters. // It can export binary or ASCII data. Binary data can be little endian // (Intel byte order) or big endian (network byte order). // // DataDest provides three advantages over direct file I/O: // * Natively handles byte order conversions // * Offers convenience methods for common data sizes and other // write operations. // * Allows writing to non-file sources (memory buffers, etc) // //----------------------------------------------------------------------------- // The DataDest API //----------------------------------------------------------------------------- // // If you are implementing a model or texture file format filter for // import, you should set the byte order that you expect for the // file format you are reading. It is safe to change the byte order // between write operations (assuming it makes sense to do so with the // format of the export data). // // Write operations: // * FIXME // // All the write functions listed above return true on success and false on // error. If any return false, either atFileLimit() will be true, or // getErrno() will return a non-zero errno value. It is safe to use the // functions to write a large number of unvalidated values and then check // for errors. // // The offset() and seek() functions can be used to get and set the current // write position, respectively. //----------------------------------------------------------------------------- // Implementing a DataDest //----------------------------------------------------------------------------- // // In most cases, the DataDest will be a FileDataDest, which writes // to a file on disk. Use the reference above or the class definition below // to see the generic DataDest API that the FileDataDest conforms to. // // If you are implementing your own DataDest to write to some other type of // output, here are the requirements a DataDest object must meet: // // * FIXME class DataDest { public: DataDest(); virtual ~DataDest(); enum EndiannessE { LittleEndian, // Intel byte order, low-order byte first (default) BigEndian, // Network byte order, high-order byte first }; // Endianness of the input data. void setEndianness( EndiannessE e ); EndiannessE getEndianness() { return m_endian; } // Perform any cleanup when done writing. void close() { internalClose(); } // Returns the size of the output written so far. size_t getFileSize() { return m_fileSize; } // Set a limit on the maximum amount of data that can be written. void setFileSizeLimit( size_t bytes ); // Returns the max size of the output size_t getFileSizeLimit() { return m_fileSizeLimit; } // Indicates if the output size is limited bool hasFileSizeLimit() { return m_hasLimit; } // Allow unrestricted file size void removeFileSizeLimit() { m_hasLimit = false; } // Move the current write position to 'offset' in the output. bool seek( off_t offset ); // Returns the current write offset. off_t offset() { return m_offset; } // Write bufLen bytes to output // Returns false if a write error occurred. bool writeBytes( const uint8_t * buf, size_t bufLen ); // Write a printf-style formatted string to output // Returns the size written in bytes (or -1 on error) ssize_t writePrintf( const char * format, ... ); // Write a printf-style formatted string to output // Returns the size written in bytes (or -1 on error) // This implementation writes the string to a buffer using snprintf, and // then calls writeBytes. writePrintf calls this function. This function // is virtual so that you can make this more efficient if you are // implementing a DataDest. virtual ssize_t writeVPrintf( const char * format, va_list ap ); // Writes a null-terminated string to output (including null) ssize_t writeAsciiz( const char * str ); // Writes a null-terminated string to output (not including null) ssize_t writeString( const char * str ); // Write an integer value of the specified size and store it in val. // Returns false if a write error occurred. bool write( int8_t val ); bool write( uint8_t val ); bool write( int16_t val ); bool write( uint16_t val ); bool write( int32_t val ); bool write( uint32_t val ); bool write( float32_t val ); // An error occured, either atFileLimit() is true, or getErrno() // is not 0. bool errorOccurred() { return m_errorOccurred; } bool atFileLimit() { return m_atFileLimit; } int getErrno() { return m_errno; } protected: virtual bool internalWrite( const uint8_t * buf, size_t bufLen ) = 0; virtual bool internalSeek( off_t offset ) = 0; virtual void internalClose() {}; void setAtFileLimit( bool o ); void setErrno( int err ); private: bool canWrite( size_t bytes ); enum { MAX_PRINTF_SIZE = 16 * 1024 }; EndiannessE m_endian; size_t m_fileSize; size_t m_fileSizeLimit; bool m_hasLimit; size_t m_offset; bool m_errorOccurred; bool m_atFileLimit; int m_errno; char m_strbuf[ MAX_PRINTF_SIZE ]; typedef uint16_t (*EndianFunction16T)( uint16_t ); typedef uint32_t (*EndianFunction32T) ( uint32_t ); typedef float (*EndianFunctionFlT) ( float ); EndianFunction16T m_endfunc16; EndianFunction32T m_endfunc32; EndianFunctionFlT m_endfuncfl; }; #endif // DATADEST_INC_H__ mm3d-1.3.7/src/libmm3d/model_texture.cc0000644000175000017500000004476710745042274014637 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "log.h" #include "texture.h" #include "texmgr.h" #include "translate.h" #ifdef MM3D_EDIT #include "modelundo.h" #include "modelstatus.h" #endif // MM3D_EDIT int Model::s_glTextures = 0; bool Model::loadTextures( ContextT context ) { LOG_PROFILE(); DrawingContext * drawContext = NULL; if ( context ) { deleteGlTextures( context ); drawContext = getDrawingContext( context ); drawContext->m_textures.clear(); } for ( unsigned t = 0; t < m_materials.size(); t++ ) { if ( drawContext ) { drawContext->m_textures.push_back( -1 ); } if ( m_materials[t]->m_filename[0] && m_materials[t]->m_type == Model::Material::MATTYPE_TEXTURE ) { Texture * tex = TextureManager::getInstance()->getTexture( m_materials[t]->m_filename.c_str() ); if ( !tex ) { #ifdef MM3D_EDIT std::string msg = transll( QT_TRANSLATE_NOOP("LowLevel", "Could not load texture") ); msg += std::string(" ") + m_materials[t]->m_filename; model_status( this, StatusError, STATUSTIME_LONG, msg.c_str() ); #endif // MM3D_EDIT tex = TextureManager::getInstance()->getDefaultTexture( m_materials[t]->m_filename.c_str() ); } if ( tex ) { m_materials[t]->m_textureData = tex; glGenTextures( 1, &(m_materials[t]->m_texture) ); s_glTextures++; if ( drawContext ) { drawContext->m_textures[t] = m_materials[t]->m_texture; } log_debug( "loaded texture %s as %d\n", tex->m_name, m_materials[t]->m_texture ); if ( context ) { glBindTexture( GL_TEXTURE_2D, m_materials[t]->m_texture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); GLuint format = tex->m_format == Texture::FORMAT_RGBA ? GL_RGBA : GL_RGB; gluBuild2DMipmaps( GL_TEXTURE_2D, format, tex->m_width, tex->m_height, format, GL_UNSIGNED_BYTE, tex->m_data ); } } else { log_error( "Could not load texture %s\n", m_materials[t]->m_filename.c_str() ); } } } if ( drawContext ) { drawContext->m_valid = true; } texture_manager_do_warning(); return true; } #ifdef MM3D_EDIT int Model::addTexture( Texture * tex ) { LOG_PROFILE(); if ( m_animationMode ) { return -1; } m_changeBits |= AddOther; if ( tex ) { int num = m_materials.size(); Material * material = Material::get(); material->m_name = tex->m_name; material->m_type = Material::MATTYPE_TEXTURE; material->m_texture = 0; material->m_textureData = tex; material->m_filename = tex->m_filename; for ( int m = 0; m < 3; m++ ) { material->m_ambient[m] = 0.2; material->m_diffuse[m] = 0.8; material->m_specular[m] = 0.0; material->m_emissive[m] = 0.0; } material->m_ambient[3] = 1.0; material->m_diffuse[3] = 1.0; material->m_specular[3] = 1.0; material->m_emissive[3] = 1.0; material->m_shininess = 0.0; //DrawingContextList m_drawingContexts; m_materials.push_back( material ); MU_AddTexture * undo = new MU_AddTexture(); undo->addTexture( num, material ); sendUndo( undo ); invalidateTextures(); return num; } else { return -1; } } int Model::addColorMaterial( const char * name ) { LOG_PROFILE(); if ( m_animationMode || name == NULL ) { return -1; } m_changeBits |= AddOther; int num = m_materials.size(); Material * material = Material::get(); material->m_name = name; material->m_type = Material::MATTYPE_BLANK; material->m_texture = 0; material->m_textureData = NULL; material->m_filename = ""; for ( int m = 0; m < 3; m++ ) { material->m_ambient[m] = 0.2; material->m_diffuse[m] = 0.8; material->m_specular[m] = 0.0; material->m_emissive[m] = 0.0; } material->m_ambient[3] = 1.0; material->m_diffuse[3] = 1.0; material->m_specular[3] = 1.0; material->m_emissive[3] = 1.0; material->m_shininess = 0.0; //DrawingContextList m_drawingContexts; m_materials.push_back( material ); MU_AddTexture * undo = new MU_AddTexture(); undo->addTexture( num, material ); sendUndo( undo ); return num; } void Model::deleteTexture( unsigned textureNum ) { LOG_PROFILE(); if ( m_animationMode ) { return; } for ( unsigned g = 0; g < m_groups.size(); g++ ) { if ( m_groups[g]->m_materialIndex == (signed) textureNum ) { setGroupTextureId( g, -1 ); } if ( m_groups[g]->m_materialIndex > (signed) textureNum ) { setGroupTextureId( g, m_groups[g]->m_materialIndex - 1 ); } } MU_DeleteTexture * undo = new MU_DeleteTexture(); undo->deleteTexture( textureNum, m_materials[ textureNum ] ); sendUndo( undo ); removeTexture( textureNum ); } bool Model::setGroupTextureId( unsigned groupNumber, int textureId ) { if ( m_animationMode ) { return false; } m_changeBits |= AddOther; if ( groupNumber >= 0 && groupNumber < m_groups.size() && textureId < (int) m_materials.size() ) { m_validBspTree = false; MU_SetTexture * undo = new MU_SetTexture(); undo->setTexture( groupNumber, textureId, m_groups[ groupNumber ]->m_materialIndex ); sendUndo( undo ); m_groups[ groupNumber ]->m_materialIndex = textureId; return true; } else { return false; } } bool Model::setTextureCoords( unsigned triangleNumber, unsigned vertexIndex, float s, float t ) { if ( m_animationMode ) { return false; } //log_debug( "setTextureCoords( %d, %d, %f, %f )\n", triangleNumber, vertexIndex, s, t ); if ( triangleNumber < m_triangles.size() && vertexIndex < 3 ) { m_validBspTree = false; MU_SetTextureCoords * undo = new MU_SetTextureCoords(); undo->addTextureCoords( triangleNumber, vertexIndex, s, t, m_triangles[ triangleNumber ]->m_s[ vertexIndex ], m_triangles[ triangleNumber ]->m_t[ vertexIndex ] ); sendUndo( undo, true ); m_triangles[ triangleNumber ]->m_s[ vertexIndex ] = s; m_triangles[ triangleNumber ]->m_t[ vertexIndex ] = t; return true; } else { return false; } } bool Model::setTextureAmbient( unsigned textureId, const float * ambient ) { if ( m_animationMode ) { return false; } if ( ambient && textureId < m_materials.size() ) { MU_SetLightProperties * undo = new MU_SetLightProperties(); undo->setLightProperties( textureId, MU_SetLightProperties::LightAmbient, ambient, m_materials[textureId]->m_ambient); sendUndo( undo ); for ( int t = 0; t < 4; t++ ) { m_materials[textureId]->m_ambient[t] = ambient[t]; } return true; } else { return false; } } bool Model::setTextureDiffuse( unsigned textureId, const float * diffuse ) { if ( m_animationMode ) { return false; } if ( diffuse && textureId < m_materials.size() ) { MU_SetLightProperties * undo = new MU_SetLightProperties(); undo->setLightProperties( textureId, MU_SetLightProperties::LightDiffuse, diffuse, m_materials[textureId]->m_diffuse); sendUndo( undo ); for ( int t = 0; t < 4; t++ ) { m_materials[textureId]->m_diffuse[t] = diffuse[t]; } return true; } else { return false; } } bool Model::setTextureSpecular( unsigned textureId, const float * specular ) { if ( m_animationMode ) { return false; } if ( specular && textureId < m_materials.size() ) { MU_SetLightProperties * undo = new MU_SetLightProperties(); undo->setLightProperties( textureId, MU_SetLightProperties::LightSpecular, specular, m_materials[textureId]->m_specular); sendUndo( undo ); for ( int t = 0; t < 4; t++ ) { m_materials[textureId]->m_specular[t] = specular[t]; } return true; } else { return false; } } bool Model::setTextureEmissive( unsigned textureId, const float * emissive ) { if ( m_animationMode ) { return false; } if ( emissive && textureId < m_materials.size() ) { MU_SetLightProperties * undo = new MU_SetLightProperties(); undo->setLightProperties( textureId, MU_SetLightProperties::LightEmissive, emissive, m_materials[textureId]->m_emissive); sendUndo( undo ); for ( int t = 0; t < 4; t++ ) { m_materials[textureId]->m_emissive[t] = emissive[t]; } return true; } else { return false; } } bool Model::setTextureShininess( unsigned textureId, float shininess ) { if ( m_animationMode ) { return false; } if ( textureId < m_materials.size() ) { MU_SetShininess * undo = new MU_SetShininess(); undo->setShininess( textureId, shininess, m_materials[textureId]->m_shininess); sendUndo( undo ); m_materials[textureId]->m_shininess = shininess; return true; } else { return false; } } void Model::setTextureName( unsigned textureId, const char * name ) { if ( m_animationMode ) { return; } if ( name && textureId < m_materials.size() ) { MU_SetTextureName * undo = new MU_SetTextureName(); undo->setTextureName( textureId, name, m_materials[ textureId ]->m_name.c_str() ); sendUndo( undo ); m_materials[ textureId ]->m_name = name; } } void Model::setMaterialTexture( unsigned textureId, Texture * tex ) { if ( m_animationMode ) { return; } if ( tex == NULL ) { removeMaterialTexture( textureId ); } else if ( textureId < m_materials.size() ) { MU_SetMaterialTexture * undo = new MU_SetMaterialTexture(); undo->setMaterialTexture( textureId, tex, m_materials[ textureId ]->m_textureData ); sendUndo( undo ); m_materials[ textureId ]->m_textureData = tex; m_materials[ textureId ]->m_filename = tex->m_filename; m_materials[ textureId ]->m_type = Material::MATTYPE_TEXTURE; invalidateTextures(); } } void Model::removeMaterialTexture( unsigned textureId ) { if ( m_animationMode ) { return; } if ( textureId < m_materials.size() ) { if ( m_materials[ textureId ]->m_type == Material::MATTYPE_TEXTURE ) { MU_SetMaterialTexture * undo = new MU_SetMaterialTexture(); undo->setMaterialTexture( textureId, NULL, m_materials[ textureId ]->m_textureData ); sendUndo( undo ); m_materials[ textureId ]->m_textureData = NULL; m_materials[ textureId ]->m_filename = ""; m_materials[ textureId ]->m_type = Material::MATTYPE_BLANK; invalidateTextures(); } } } bool Model::setTextureSClamp( unsigned textureId, bool clamp ) { if ( textureId < m_materials.size() ) { MU_SetMaterialClamp * undo = new MU_SetMaterialClamp(); undo->setMaterialClamp( textureId, true, clamp, m_materials[ textureId ]->m_sClamp ); sendUndo( undo ); m_materials[ textureId ]->m_sClamp = clamp; return true; } return false; } bool Model::setTextureTClamp( unsigned textureId, bool clamp ) { if ( textureId < m_materials.size() ) { MU_SetMaterialClamp * undo = new MU_SetMaterialClamp(); undo->setMaterialClamp( textureId, false, clamp, m_materials[ textureId ]->m_tClamp ); sendUndo( undo ); m_materials[ textureId ]->m_tClamp = clamp; return true; } return false; } void Model::noTexture( unsigned id ) { LOG_PROFILE(); for ( unsigned t = 0; t < m_groups.size(); t++ ) { if ( (unsigned) m_groups[t]->m_materialIndex == id ) { m_groups[t]->m_materialIndex = -1; } } } #endif // MM3D_EDIT int Model::getGroupTextureId( unsigned groupNumber ) const { if ( groupNumber >= 0 && groupNumber < m_groups.size() ) { return m_groups[ groupNumber ]->m_materialIndex; } else { return -1; } } bool Model::getTextureCoords( unsigned triangleNumber, unsigned vertexIndex, float & s, float & t ) const { if ( triangleNumber < m_triangles.size() && vertexIndex < 3 ) { s = m_triangles[ triangleNumber ]->m_s[ vertexIndex ]; t = m_triangles[ triangleNumber ]->m_t[ vertexIndex ]; return true; } else { return false; } } Texture * Model::getTextureData( unsigned textureId ) { if ( textureId >= 0 && textureId < m_materials.size() ) { return m_materials[textureId]->m_textureData; } else { return NULL; } } bool Model::getTextureAmbient( unsigned textureId, float * ambient ) const { if ( ambient && textureId < m_materials.size() ) { for ( int t = 0; t < 4; t++ ) { ambient[t] = m_materials[textureId]->m_ambient[t]; } return true; } else { return false; } } bool Model::getTextureDiffuse( unsigned textureId, float * diffuse ) const { if ( diffuse && textureId < m_materials.size() ) { for ( int t = 0; t < 4; t++ ) { diffuse[t] = m_materials[textureId]->m_diffuse[t]; } return true; } else { return false; } } bool Model::getTextureSpecular( unsigned textureId, float * specular ) const { if ( specular && textureId < m_materials.size() ) { for ( int t = 0; t < 4; t++ ) { specular[t] = m_materials[textureId]->m_specular[t]; } return true; } else { return false; } } bool Model::getTextureEmissive( unsigned textureId, float * emissive ) const { if ( emissive && textureId < m_materials.size() ) { for ( int t = 0; t < 4; t++ ) { emissive[t] = m_materials[textureId]->m_emissive[t]; } return true; } else { return false; } } bool Model::getTextureShininess( unsigned textureId, float & shininess ) const { if ( textureId < m_materials.size() ) { shininess = m_materials[textureId]->m_shininess; return true; } else { return false; } } bool Model::getTextureSClamp( unsigned textureId ) const { if ( textureId < m_materials.size() ) { return m_materials[ textureId ]->m_sClamp; } return false; } bool Model::getTextureTClamp( unsigned textureId ) const { if ( textureId < m_materials.size() ) { return m_materials[ textureId ]->m_tClamp; } return false; } const char * Model::getTextureName( unsigned textureId ) const { if ( textureId >= 0 && textureId < m_materials.size() ) { return m_materials[textureId]->m_name.c_str(); } else { return NULL; } } const char * Model::getTextureFilename( unsigned textureId ) const { if ( textureId >= 0 && textureId < m_materials.size() ) { return m_materials[textureId]->m_filename.c_str(); } else { return NULL; } } int Model::getMaterialColor( unsigned materialIndex, unsigned c, unsigned v ) const { if ( materialIndex < m_materials.size() && c < 4 && v < 4 ) { return m_materials[ materialIndex ]->m_color[v][c]; } else { return 0; } } Model::Material::MaterialTypeE Model::getMaterialType( unsigned materialIndex ) const { if ( materialIndex < m_materials.size() ) { return m_materials[ materialIndex ]->m_type; } else { return Material::MATTYPE_BLANK; } } int Model::getMaterialByName( const char * const materialName, bool ignoreCase ) const { int (*compare)(const char *, const char *); compare = ignoreCase ? strcasecmp : strcmp; int matNumber = -1; for ( unsigned m = 0; m < m_materials.size(); m++ ) { if ( compare( materialName, m_materials[m]->m_name.c_str() ) == 0 ) { matNumber = m; break; } } return matNumber; } DrawingContext * Model::getDrawingContext( ContextT context ) { DrawingContextList::iterator it; for ( it = m_drawingContexts.begin(); it != m_drawingContexts.end(); it++ ) { if ( (*it)->m_context == context ) { return (*it); } } DrawingContext * drawContext = new DrawingContext; drawContext->m_context = context; drawContext->m_valid = false; m_drawingContexts.push_back( drawContext ); return drawContext; } void Model::invalidateTextures() { DrawingContextList::iterator it; for ( it = m_drawingContexts.begin(); it != m_drawingContexts.end(); it++ ) { (*it)->m_valid = false; } } void Model::deleteGlTextures( ContextT context ) { DrawingContext * drawContext = getDrawingContext( context ); for ( unsigned t = 0; t < drawContext->m_textures.size(); t++ ) { int texId = drawContext->m_textures[t]; if ( texId > 0 ) { glDeleteTextures( 1, (GLuint *) &texId ); s_glTextures--; } drawContext->m_textures[t] = -1; } drawContext->m_valid = false; } void Model::removeContext( ContextT context ) { DrawingContext * drawContext = NULL; DrawingContextList::iterator it; for ( it = m_drawingContexts.begin(); drawContext == NULL && it != m_drawingContexts.end(); it++ ) { if ( (*it)->m_context == context ) { drawContext = *it; deleteGlTextures( context ); break; } } if ( drawContext ) { m_drawingContexts.erase( it ); delete drawContext; } } mm3d-1.3.7/src/libmm3d/model_insert.cc0000644000175000017500000004261110746733504014431 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "log.h" #ifdef MM3D_EDIT void Model::insertVertex( unsigned index, Model::Vertex * vertex ) { if ( m_animationMode ) { return; } m_changeBits |= AddGeometry; invalidateNormals(); if ( index == m_vertices.size() ) { m_vertices.push_back( vertex ); } else if ( index < m_vertices.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_vertices.begin(); it != m_vertices.end(); it++ ) { if ( count == index ) { m_vertices.insert( it, vertex ); adjustVertexIndices( index, +1 ); break; } count++; } } else { log_error( "insertVertex( %d ) index out of range\n", index ); } } void Model::removeVertex( unsigned index ) { if ( m_animationMode ) { return; } m_changeBits |= AddGeometry; invalidateNormals(); if ( index < m_vertices.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_vertices.begin(); it != m_vertices.end(); it++ ) { if ( count == index ) { m_vertices.erase( it ); adjustVertexIndices( index, -1 ); break; } count++; } } else { log_error( "removeVertex( %d ) index out of range\n", index ); } } void Model::insertTriangle( unsigned index, Model::Triangle * triangle ) { if ( m_animationMode ) { return; } m_changeBits |= AddGeometry; invalidateNormals(); if ( index == m_triangles.size() ) { m_triangles.push_back( triangle ); } else if ( index < m_triangles.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_triangles.begin(); it != m_triangles.end(); it++ ) { if ( count == index ) { m_triangles.insert( it, triangle ); adjustTriangleIndices( index, +1 ); break; } count++; } } else { log_error( "insertTriangle( %d ) index out of range\n", index ); } } void Model::removeTriangle( unsigned index ) { if ( m_animationMode ) { return; } m_changeBits |= AddGeometry; invalidateNormals(); if ( index < m_triangles.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_triangles.begin(); it != m_triangles.end(); it++ ) { if ( count == index ) { m_triangles.erase( it ); adjustTriangleIndices( index, -1 ); break; } count++; } } else { log_error( "removeTriangle( %d ) index out of range\n", index ); } } void Model::insertGroup( unsigned index, Model::Group * group ) { if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( index == m_groups.size() ) { m_groups.push_back( group ); } else if ( index < m_groups.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_groups.begin(); it != m_groups.end(); it++ ) { if ( count == index ) { m_groups.insert( it, group ); break; } count++; } } else { log_error( "insertGroup( %d ) index out of range\n", index ); } } void Model::removeGroup( unsigned index ) { if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( index < m_groups.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_groups.begin(); it != m_groups.end(); it++ ) { if ( count == index ) { m_groups.erase( it ); break; } count++; } } else { log_error( "removeGroup( %d ) index out of range\n", index ); } } void Model::insertBoneJoint( unsigned index, Model::Joint * joint ) { if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( index == m_joints.size() ) { m_joints.push_back( joint ); // Append keyframe list for ( unsigned anim = 0; anim < m_skelAnims.size(); anim++ ) { SkelAnim * sa = m_skelAnims[anim]; log_debug( "appended keyframe list for joint %d\n", index ); sa->m_jointKeyframes.push_back( KeyframeList() ); } } else if ( index < m_joints.size() ) { // Adjust parent relationships unsigned j; for ( j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_parent >= (signed) index ) { m_joints[j]->m_parent++; } } // Adjust joint indices of keyframes after this joint for ( unsigned anim = 0; anim < m_skelAnims.size(); anim++ ) { SkelAnim * sa = m_skelAnims[anim]; for ( j = index; j < sa->m_jointKeyframes.size(); j++ ) { for ( unsigned k = 0; k < sa->m_jointKeyframes[j].size(); k++ ) { sa->m_jointKeyframes[j][k]->m_jointIndex++; } } // Insert joint into keyframe list if ( index == sa->m_jointKeyframes.size() ) { log_debug( "appended keyframe list for joint %d\n", j ); sa->m_jointKeyframes.push_back( KeyframeList() ); } else { JointKeyframeList::iterator it = sa->m_jointKeyframes.begin(); for ( j = 0; j < sa->m_jointKeyframes.size(); j++ ) { if ( j == index ) { log_debug( "inserted keyframe list for joint %d\n", j ); sa->m_jointKeyframes.insert( it, KeyframeList() ); break; } it++; } } } { InfluenceList::iterator it; // Adjust vertex assignments for ( unsigned v = 0; v < m_vertices.size(); v++ ) { InfluenceList & l = m_vertices[v]->m_influences; for ( it = l.begin(); it != l.end(); it++ ) { if ( (*it).m_boneId >= (signed) index ) { (*it).m_boneId++; } } } // Adjust point assignments for ( unsigned p = 0; p < m_points.size(); p++ ) { InfluenceList & l = m_points[p]->m_influences; for ( it = l.begin(); it != l.end(); it++ ) { if ( (*it).m_boneId >= (signed) index ) { (*it).m_boneId++; } } } } unsigned count = 0; vector::iterator it; for ( it = m_joints.begin(); it != m_joints.end(); it++ ) { if ( count == index ) { m_joints.insert( it, joint ); break; } count++; } m_validJoints = false; } else { log_error( "insertBoneJoint( %d ) index out of range\n", index ); } } void Model::removeBoneJoint( unsigned joint ) { log_debug( "removeBoneJoint( %d )\n", joint ); if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( joint < m_joints.size() ) { // Adjust parent relationships unsigned j = 0; for ( j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_parent == (signed) joint ) { m_joints[j]->m_parent = m_joints[joint]->m_parent; } else if ( m_joints[j]->m_parent > (signed) joint ) { m_joints[j]->m_parent--; } } // Adjust skeletal animations unsigned anim = 0; for ( anim = 0; anim < m_skelAnims.size(); anim++ ) { SkelAnim * sa = m_skelAnims[anim]; if ( joint < sa->m_jointKeyframes.size() ) { // Delete joint keyframes for ( int index = sa->m_jointKeyframes[joint].size() - 1; index >= 0; index-- ) { log_debug( "deleting keyframe %d for joint %d\n", index, joint ); deleteSkelAnimKeyframe( anim, sa->m_jointKeyframes[joint][index]->m_frame, joint, sa->m_jointKeyframes[joint][index]->m_isRotation ); } // Remove joint from keyframe list JointKeyframeList::iterator it = sa->m_jointKeyframes.begin(); for ( j = 0; j < sa->m_jointKeyframes.size(); j++ ) { if ( j == joint ) { log_debug( "removed keyframe list for joint %d\n", j ); sa->m_jointKeyframes.erase( it ); break; } it++; } } } // Adjust joint indices of keyframes after this joint for ( anim = 0; anim < m_skelAnims.size(); anim++ ) { SkelAnim * sa = m_skelAnims[anim]; for ( j = joint; j < sa->m_jointKeyframes.size(); j++ ) { for ( unsigned index = 0; index < sa->m_jointKeyframes[j].size(); index++ ) { sa->m_jointKeyframes[j][index]->m_jointIndex--; } } } { InfluenceList::iterator it; // Adjust vertex assignments for ( unsigned v = 0; v < m_vertices.size(); v++ ) { InfluenceList & l = m_vertices[v]->m_influences; for ( it = l.begin(); it != l.end(); it++ ) { if ( (*it).m_boneId > (signed) joint ) { (*it).m_boneId--; } } } // Adjust point assignments for ( unsigned p = 0; p < m_points.size(); p++ ) { InfluenceList & l = m_points[p]->m_influences; for ( it = l.begin(); it != l.end(); it++ ) { if ( (*it).m_boneId > (signed) joint ) { (*it).m_boneId--; } } } } vector::iterator it; unsigned count; for ( count = 0, it = m_joints.begin(); it != m_joints.end(); it++ ) { if ( count == joint ) { m_joints.erase( it ); break; } count++; } m_validJoints = false; } else { log_error( "removeBoneJoint( %d ) index out of range\n", joint ); } } void Model::insertInfluence( const Position & pos, unsigned index, const InfluenceT & influence ) { m_changeBits |= AddOther; InfluenceList * l = NULL; if ( pos.type == PT_Vertex ) { if ( pos.index < m_vertices.size() ) { l = &m_vertices[ pos.index ]->m_influences; } } else if ( pos.type == PT_Point ) { if ( pos.index < m_points.size() ) { l = &m_points[ pos.index ]->m_influences; } } if ( l == NULL ) { return; } InfluenceList::iterator it = l->begin(); while ( index > 0 ) { index--; it++; } if ( it == l->end() ) { l->push_back( influence ); } else { l->insert( it, influence ); } } void Model::removeInfluence( const Position & pos, unsigned index ) { m_changeBits |= AddOther; InfluenceList * l = NULL; if ( pos.type == PT_Vertex ) { if ( pos.index < m_vertices.size() ) { l = &m_vertices[ pos.index ]->m_influences; } } else if ( pos.type == PT_Point ) { if ( pos.index < m_points.size() ) { l = &m_points[ pos.index ]->m_influences; } } if ( l == NULL ) { return; } InfluenceList::iterator it = l->begin(); while ( index > 0 ) { index--; it++; } if ( it != l->end() ) { l->erase( it ); } } void Model::insertPoint( unsigned index, Model::Point * point ) { if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( index == m_points.size() ) { m_points.push_back( point ); } else if ( index < m_points.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_points.begin(); it != m_points.end(); it++ ) { if ( count == index ) { m_points.insert( it, point ); break; } count++; } } else { log_error( "insertPoint( %d ) index out of range\n", index ); } } void Model::removePoint( unsigned point ) { log_debug( "removePoint( %d )\n", point ); if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( point < m_points.size() ) { vector::iterator it; unsigned count; for ( count = 0, it = m_points.begin(); it != m_points.end(); it++ ) { if ( count == point ) { m_points.erase( it ); break; } count++; } } else { log_error( "removePoint( %d ) index out of range\n", point ); } } void Model::insertProjection( unsigned index, Model::TextureProjection * proj ) { if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( index == m_projections.size() ) { m_projections.push_back( proj ); } else if ( index < m_projections.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_projections.begin(); it != m_projections.end(); it++ ) { if ( count == index ) { m_projections.insert( it, proj ); adjustProjectionIndices( index, +1 ); break; } count++; } } else { log_error( "insertProjection( %d ) index out of range\n", index ); } } void Model::removeProjection( unsigned proj ) { log_debug( "removeProjection( %d )\n", proj ); if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( proj < m_projections.size() ) { vector::iterator it; unsigned count; for ( count = 0, it = m_projections.begin(); it != m_projections.end(); it++ ) { if ( count == proj ) { m_projections.erase( it ); adjustProjectionIndices( proj, -1 ); break; } count++; } } else { log_error( "removeProjection( %d ) index out of range\n", proj ); } } void Model::insertTexture( unsigned index, Model::Material * texture ) { if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( index == m_materials.size() ) { m_materials.push_back( texture ); invalidateTextures(); } else if ( index < m_materials.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_materials.begin(); it != m_materials.end(); it++ ) { if ( count == index ) { m_materials.insert( it, texture ); invalidateTextures(); break; } count++; } } else { log_error( "insertTexture( %d ) index out of range\n", index ); } } void Model::removeTexture( unsigned index ) { if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( index < m_materials.size() ) { unsigned count = 0; vector::iterator it; for ( it = m_materials.begin(); it != m_materials.end(); it++ ) { if ( count == index ) { m_materials.erase( it ); break; } count++; } } else { log_error( "removeTexture( %d ) index out of range\n", index ); } } void Model::adjustVertexIndices( unsigned index, int count ) { for ( unsigned t = 0; t < m_triangles.size(); t++ ) { for ( unsigned v = 0; v < 3; v++ ) { if ( m_triangles[t]->m_vertexIndices[v] >= index ) { m_triangles[t]->m_vertexIndices[v] += count; } } } } void Model::adjustTriangleIndices( unsigned index, int count ) { for ( unsigned g = 0; g < m_groups.size(); g++ ) { Group * grp = m_groups[g]; std::set newSet; for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { if ( (unsigned) *it >= index ) newSet.insert( *it + count ); else newSet.insert( *it ); } grp->m_triangleIndices.swap( newSet ); } } void Model::adjustProjectionIndices( unsigned index, int count ) { for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_projection >= (int) index ) { m_triangles[t]->m_projection += count; } } } #endif // MM3D_EDIT mm3d-1.3.7/src/libmm3d/cobfilter.cc0000644000175000017500000012547710767317432013733 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "cobfilter.h" #include "model.h" #include "texture.h" #include "log.h" #include "binutil.h" #include "misc.h" #include "filtermgr.h" #include "endianconfig.h" #include "texmgr.h" #include #include #include #ifdef WIN32 #include #else #include #endif // WIN32 #include using std::list; using std::string; #ifdef PLUGIN static CobFilter * s_filter = NULL; #endif // PLUGIN static void _invertModelNormals( Model * model ) { size_t tcount = model->getTriangleCount(); for ( size_t t = 0; t < tcount; t++ ) { model->invertNormals( t ); } } static float _valToCoeff( float * fval ) { float rval = 0.0; if ( fval != NULL ) { for ( int i = 0; i < 3; i++ ) { rval += fval[i]; } rval /= 3.0f; } return rval; } static bool _float_equiv( float rhs, float lhs ) { if ( fabs( rhs - lhs ) < 0.0001f ) { return true; } else { return false; } } CobFilter::CobFilter() { } CobFilter::~CobFilter() { } Model::ModelErrorE CobFilter::readFile( Model * model, const char * const filename ) { // TODO: At some point it would be nice to handle joints and animation, maybe... Model::ModelErrorE err = Model::ERROR_NONE; m_fp = fopen( filename, "rb" ); if ( m_fp ) { m_meshMaterials.clear(); m_modelPath = ""; m_modelBaseName = ""; m_modelFullName = ""; normalizePath( filename, m_modelFullName, m_modelPath, m_modelBaseName ); model->setFilename( m_modelFullName.c_str() ); fseek( m_fp, 0, SEEK_END ); m_fileLength = ftell( m_fp ); fseek( m_fp, 0, SEEK_SET ); m_fileBuf = new uint8_t[m_fileLength]; m_bufPos = m_fileBuf; fread( m_fileBuf, m_fileLength, 1, m_fp ); fclose( m_fp ); m_model = model; err = readFileHeader(); if ( err == Model::ERROR_NONE ) { ChunkHeaderT header; if ( m_isBinary ) { while ( readBChunkHeader( header ) && header.type != CT_EOF ) { m_chunkStart = m_bufPos; m_chunkEnd = m_chunkStart + header.length; switch ( header.type ) { case CT_Polygon: readPolygonChunk( header ); break; case CT_Material: readMaterialChunk( header ); break; default: readBUnknownChunk( header ); break; } } } else { while ( readAChunkHeader( header ) && header.type != CT_EOF ) { m_chunkStart = m_bufPos; m_chunkEnd = m_chunkStart + header.length; switch ( header.type ) { case CT_Polygon: readPolygonChunk( header ); break; case CT_Material: readMaterialChunk( header ); break; default: readAUnknownChunk( header ); break; } } } } delete[] m_fileBuf; m_fileBuf = NULL; m_bufPos = NULL; m_fp = NULL; _invertModelNormals( model ); } else { switch ( errno ) { case EACCES: case EPERM: return Model::ERROR_NO_ACCESS; case ENOENT: return Model::ERROR_NO_FILE; case EISDIR: return Model::ERROR_BAD_DATA; default: return Model::ERROR_FILE_OPEN; } } return err; } Model::ModelErrorE CobFilter::writeFile( Model * model, const char * const filename, ModelFilter::Options * o ) { if ( filename == NULL || filename[0] == '\0' ) { return Model::ERROR_BAD_ARGUMENT; } m_fp = fopen( filename, "wb" ); if ( m_fp == NULL ) { switch ( errno ) { case EACCES: case EPERM: return Model::ERROR_NO_ACCESS; case ENOENT: return Model::ERROR_NO_FILE; case EISDIR: return Model::ERROR_BAD_DATA; default: return Model::ERROR_FILE_OPEN; } } m_model = model; _invertModelNormals( model ); m_modelPath = ""; m_modelBaseName = ""; m_modelFullName = ""; normalizePath( filename, m_modelFullName, m_modelPath, m_modelBaseName ); m_lastChunkSizeOffset = 0; m_nextChunkId = 10001; fwrite( "Caligari V00.01BLH \n", 32, 1, m_fp ); writeBUngrouped(); writeBGrouped(); writeBEOF(); fclose( m_fp ); _invertModelNormals( model ); model->operationComplete( "Invert normals for save" ); return Model::ERROR_NONE; } bool CobFilter::canRead( const char * filename ) { log_debug( "canRead( %s )\n", filename ); log_debug( " true\n" ); return true; } bool CobFilter::canWrite( const char * filename ) { log_debug( "canWrite( %s )\n", filename ); log_debug( " false\n" ); return false; } bool CobFilter::canExport( const char * filename ) { log_debug( "canExport( %s )\n", filename ); log_debug( " true\n" ); return true; } bool CobFilter::isSupported( const char * filename ) { log_debug( "isSupported( %s )\n", filename ); unsigned len = strlen( filename ); if ( len >= 4 && strcasecmp( &filename[len-4], ".cob" ) == 0 ) { log_debug( " true\n" ); return true; } else { log_debug( " false\n" ); return false; } } list< string > CobFilter::getReadTypes() { list rval; rval.push_back( "*.cob" ); return rval; } list< string > CobFilter::getWriteTypes() { list rval; rval.push_back( "*.cob" ); return rval; } //------------------------------------------------------------------ // Protected Methods //------------------------------------------------------------------ CobFilter::ChunkTypeE CobFilter::chunkCharsToType( const char * str ) { if ( strcmp( str, "END " ) == 0 ) { return CT_EOF; } else if ( strcmp( str, "PolH" ) == 0 ) { return CT_Polygon; } else if ( strcmp( str, "Mat1" ) == 0 ) { return CT_Material; } return CT_Unknown; } CobFilter::MeshMaterialT * CobFilter::getMeshMaterial( int chunkId, int matNumber ) { for ( size_t m = 0; m < m_meshMaterials.size(); m++ ) { if ( m_meshMaterials[m].meshChunkId == chunkId && m_meshMaterials[m].matNumber == matNumber ) { return &m_meshMaterials[m]; } } log_debug( "creating material for poly mesh %d, material %d\n", chunkId, matNumber ); MeshMaterialT mMat; mMat.meshChunkId = chunkId; mMat.matNumber = matNumber; mMat.groupId = -1; m_meshMaterials.push_back( mMat ); return &m_meshMaterials.back(); } int32_t CobFilter::getNextChunkId() { return m_nextChunkId++; } //------------------------------------------------------------------ // Common read functions Model::ModelErrorE CobFilter::readFileHeader() { if ( strncmp( (char*) m_bufPos, "Caligari ", 9 ) != 0 ) { return Model::ERROR_BAD_MAGIC; } m_bufPos += 9; if ( strncmp( (char*) m_bufPos, "V00.01", 6 ) != 0 ) { return Model::ERROR_UNSUPPORTED_VERSION; } m_bufPos += 6; if ( m_bufPos[0] == 'B' ) { m_isBinary = true; } else { m_isBinary = false; } m_bufPos++; if ( strncmp( (char*) m_bufPos, "LH", 2 ) == 0 ) { m_isLittleEndian = true; } else { m_isLittleEndian = false; } m_bufPos += 2; // Last 14 bytes are pad and newline m_bufPos += 14; return Model::ERROR_NONE; } bool CobFilter::readPolygonChunk( const CobFilter::ChunkHeaderT & header ) { log_debug( "reading polygon chunk %d of %d bytes\n", header.chunkId, header.length ); PolygonMeshT mesh; if ( m_isBinary ) { readBPolygonChunk( header, mesh ); } else { readAPolygonChunk( header, mesh ); } log_debug( "verts %d uvs %d faces %d\n", mesh.vertexList.size(), mesh.uvList.size(), mesh.faceList.size() ); int vertBase = m_model->getVertexCount(); size_t v; for ( v = 0; v < mesh.vertexList.size(); v++ ) { m_model->addVertex( mesh.vertexList[v].coord[0], mesh.vertexList[v].coord[1], mesh.vertexList[v].coord[2] ); } MeshMaterialT * mMat = NULL; // Faces size_t fcount = mesh.faceList.size(); for ( size_t f = 0; f < fcount; f++ ) { PolygonFaceT * face = &mesh.faceList[f]; if ( mMat == NULL || mMat->matNumber != face->matNumber ) { mMat = getMeshMaterial( header.chunkId, face->matNumber ); if ( mMat->groupId < 0 ) { mMat->groupId = m_model->addGroup( mesh.name.c_str() ); } } if ( (face->flags & FF_HOLE) == 0 ) { size_t vcount = face->faceVertices.size(); if ( vcount > 2 ) { size_t v = 0; for ( v = 0; v < vcount - 2; v++ ) { int tri = m_model->addTriangle( face->faceVertices[0].vertex + vertBase, face->faceVertices[v+1].vertex + vertBase, face->faceVertices[v+2].vertex + vertBase ); if ( !mesh.uvList.empty() ) { m_model->setTextureCoords( tri, 0, mesh.uvList[ face->faceVertices[0].uvCoord ].u, mesh.uvList[ face->faceVertices[0].uvCoord ].v ); m_model->setTextureCoords( tri, 1, mesh.uvList[ face->faceVertices[v+1].uvCoord ].u, mesh.uvList[ face->faceVertices[v+1].uvCoord ].v ); m_model->setTextureCoords( tri, 2, mesh.uvList[ face->faceVertices[v+2].uvCoord ].u, mesh.uvList[ face->faceVertices[v+2].uvCoord ].v ); } m_model->addTriangleToGroup( mMat->groupId, tri ); } } } } m_bufPos = m_chunkEnd; return true; } bool CobFilter::readMaterialChunk( const CobFilter::ChunkHeaderT & header ) { log_debug( "reading material chunk %d of %d bytes\n", header.chunkId, header.length ); MaterialT material; if ( m_isBinary ) { readBMaterialChunk( header, material ); } else { readAMaterialChunk( header, material ); } log_debug( "read material %d\n", material.matNumber ); log_debug( " mat color: %f %f %f %f\n", material.red , material.green , material.blue , material.alpha ); log_debug( " mat coeff: %f %f %f %f\n", material.ambient , material.specular , material.hilight , material.refraction ); // Texture map if ( !material.texFile.empty() ) { Texture * tex = TextureManager::getInstance()->getTexture( material.texFile.c_str() ); material.materialId = m_model->addTexture( tex ); } else { char name[64]; sprintf( name, "Material%d", m_model->getTextureCount() ); log_debug( " using name '%s'\n", name ); material.materialId = m_model->addColorMaterial( name ); } float fval[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; fval[0] = material.red; fval[1] = material.green; fval[2] = material.blue; fval[3] = material.alpha; m_model->setTextureDiffuse( material.materialId, fval ); fval[0] = material.red * material.ambient; fval[1] = material.green * material.ambient; fval[2] = material.blue * material.ambient; fval[3] = material.alpha * material.ambient; m_model->setTextureAmbient( material.materialId, fval ); fval[0] = material.red * material.specular; fval[1] = material.green * material.specular; fval[2] = material.blue * material.specular; fval[3] = material.alpha * material.specular; m_model->setTextureSpecular( material.materialId, fval ); fval[0] = material.red * material.hilight; fval[1] = material.green * material.hilight; fval[2] = material.blue * material.hilight; fval[3] = material.alpha * material.hilight; m_model->setTextureEmissive( material.materialId, fval ); MeshMaterialT * mMat = getMeshMaterial( header.parentId, material.matNumber ); if ( mMat->groupId >= 0 ) { m_model->setGroupTextureId( mMat->groupId, material.materialId ); m_model->setGroupAngle( mMat->groupId, material.facetAngle ); if ( !material.texFile.empty() ) { if( !_float_equiv( material.uOffset, 0.0f ) || !_float_equiv( material.vOffset, 0.0f ) || !_float_equiv( material.uRepeat, 0.1f ) || !_float_equiv( material.vRepeat, 0.1f ) ) { log_debug( "adjusting coordinates for group %d (chunk %d)\n", mMat->groupId, mMat->meshChunkId ); std::list triangles = m_model->getGroupTriangles( mMat->groupId ); std::list::iterator it; for ( it = triangles.begin(); it != triangles.end(); it++ ) { float u = 0.0f; float v = 0.0f; for ( int i = 0; i < 3; i++ ) { m_model->getTextureCoords( (*it), i, u, v ); u = (u * material.uRepeat) + material.uOffset; v = (v * material.vRepeat) + material.vOffset; m_model->setTextureCoords( (*it), i, u, v ); } } } } } m_bufPos = m_chunkEnd; return true; } //------------------------------------------------------------------ // ASCII read functions void CobFilter::skipASpace() { /* log_debug( "skipping space at '%c%c%c%c'\n", m_bufPos[0], m_bufPos[1], m_bufPos[2], m_bufPos[3] ); */ while( isspace( m_bufPos[0] ) ) { m_bufPos++; } } bool CobFilter::skipAString( const char * str ) { skipASpace(); /* log_debug( "skipping string %s at '%c%c%c%c'\n", str, m_bufPos[0], m_bufPos[1], m_bufPos[2], m_bufPos[3] ); */ size_t len = strlen(str); if ( strncmp( (char *) m_bufPos, str, len) == 0 ) { m_bufPos += len; return true; } return false; } int32_t CobFilter::readALong() { skipASpace(); /* log_debug( "reading long at '%c%c%c%c'\n", m_bufPos[0], m_bufPos[1], m_bufPos[2], m_bufPos[3] ); */ int32_t rval = atoi( (char *) m_bufPos ); if ( m_bufPos[0] == '-' ) { m_bufPos++; } while ( isdigit( m_bufPos[0] ) ) { m_bufPos++; } return rval; } int16_t CobFilter::readAShort() { return readALong(); } char CobFilter::readAChar() { char rval = (char) m_bufPos[0]; m_bufPos++; return rval; } float CobFilter::readAFloat() { skipASpace(); float rval = 0.0f; size_t len = 0; if ( sscanf( (char*) m_bufPos, "%f%n", &rval, &len ) > 0 ) { m_bufPos += len; } return rval; } double CobFilter::readADouble() { skipASpace(); float rval = 0.0; size_t len = 0; if ( sscanf( (char*) m_bufPos, "%f%n", &rval, &len ) > 0 ) { m_bufPos += len; } return rval; } bool CobFilter::readAString( std::string & str ) { skipASpace(); size_t len = 0; while ( !isspace( m_bufPos[len] ) ) { len++; } str.assign( (char*) m_bufPos, len ); m_bufPos += len; return true; } bool CobFilter::readAName( std::string & str ) { skipAString( "Name" ); readAString( str ); const char * ptr = str.c_str(); const char * off = strchr( ptr, ',' ); // Command and after is dupecount, and ignore and remove it if ( off != NULL ) { str.resize( off - ptr ); } return true; } bool CobFilter::readALocalAxes( CobFilter::LocalAxesT & axes ) { int i = 0; skipAString( "center" ); for ( i = 0; i < 3; i++ ) { axes.center[i] = readADouble(); } skipAString( "x axis" ); for ( i = 0; i < 3; i++ ) { axes.xAxis[i] = readADouble(); } skipAString( "y axis" ); for ( i = 0; i < 3; i++ ) { axes.yAxis[i] = readADouble(); } skipAString( "z axis" ); for ( i = 0; i < 3; i++ ) { axes.zAxis[i] = readADouble(); } return true; } bool CobFilter::readACurrentPosition( CobFilter::CurrentPositionT & pos ) { int r = 0; int c = 0; skipAString( "Transform" ); for ( r = 0; r < 3; r++ ) { for ( c = 0; c < 4; c++ ) { pos.mat[r][c] = readADouble(); } } // ignore last row for ( c = 0; c < 4; c++ ) { readADouble(); } return true; } bool CobFilter::readAChunkHeader( CobFilter::ChunkHeaderT & header ) { strncpy( header.chunkChars, (char*) m_bufPos, 4 ); header.chunkChars[4] = '\0'; m_bufPos += 4; header.type = chunkCharsToType( header.chunkChars ); if ( header.type == CT_EOF ) { return true; // We're done } skipASpace(); if ( m_bufPos[0] != 'V' ) { log_error( "version indicator not found\n" ); return false; } m_bufPos++; header.majorVersion = readAShort(); m_bufPos++; header.minorVersion = readAShort(); skipASpace(); skipAString( "Id" ); header.chunkId = readALong(); skipAString( "Parent" ); header.parentId = readALong(); skipAString( "Size" ); header.length = readALong(); return true; } bool CobFilter::readAPolygonChunk( const CobFilter::ChunkHeaderT & header, CobFilter::PolygonMeshT & mesh ) { // Versions 0.2 through 0.5 are identical // Version 0.6+ adds additional flags // // Name // Local Axes // Current Position // Local Vertex List // UV Vertex List // Face List // Additional Flags (0.6+) readAName( mesh.name ); readALocalAxes( mesh.localAxes ); readACurrentPosition( mesh.currentPosition ); Matrix m; mesh.currentPosition.toMatrix( m ); // Vertices skipAString( "World Vertices" ); size_t vcount = readALong(); for ( size_t v = 0; v < vcount; v++ ) { double coord[4]; coord[0] = readAFloat(); coord[1] = readAFloat(); coord[2] = readAFloat(); coord[3] = 1.0; m.apply( coord ); VertexT vert; vert.coord[0] = coord[0]; vert.coord[1] = coord[1]; vert.coord[2] = coord[2]; mesh.vertexList.push_back( vert ); } // UV Coordinates skipAString( "Texture Vertices" ); size_t uvcount = readALong(); TextureCoordT tc; for ( size_t uv = 0; uv < uvcount; uv++ ) { tc.u = readAFloat(); tc.v = readAFloat(); mesh.uvList.push_back( tc ); } // Faces skipAString( "Faces" ); size_t fcount = readALong(); for ( size_t f = 0; f < fcount; f++ ) { PolygonFaceT face; skipASpace(); if ( skipAString( "Face verts" ) ) { // Read face size_t vcount = readALong(); skipAString( "flags" ); face.flags = readALong(); skipAString( "mat" ); face.matNumber = readALong(); while( vcount ) { PolygonVertexT vert; skipAString("<"); vert.vertex = readALong(); skipAString(","); vert.uvCoord = readALong(); skipAString(">"); vcount--; face.faceVertices.push_back( vert ); } } else { // Read hole // HOLE faces are not supported, ignore them skipAString( "Hole verts" ); size_t vcount = readALong(); log_warning( "skipping %d vertices in hole\n", vcount ); char * pos = (char *) m_bufPos; while ( pos && vcount > 0 ) { pos = strchr( pos, '>' ); // end of vertex indicator if ( pos ) { pos++; } vcount--; } m_bufPos = (uint8_t *) pos; } mesh.faceList.push_back( face ); } return true; } bool CobFilter::readAMaterialChunk( const CobFilter::ChunkHeaderT & header, CobFilter::MaterialT & material ) { skipAString( "mat#" ); material.matNumber = readALong(); skipAString( "shader:" ); std::string ignoreStr; readAString( ignoreStr ); // shader type skipAString( "facet:" ); std::string facetType; readAString( facetType ); material.facetAngle = 180; if ( strcmp( facetType.c_str(), "faceted" ) == 0 ) { material.facetAngle = 0; } else if ( strncmp( facetType.c_str(), "auto", 4 ) == 0 ) { material.facetAngle = atoi( &(facetType.c_str()[4]) ); } skipAString( "rgb" ); material.red = readAFloat(); skipAString( "," ); material.green = readAFloat(); skipAString( "," ); material.blue = readAFloat(); skipAString( "alpha" ); material.alpha = readAFloat(); skipAString( "ka" ); material.ambient = readAFloat(); skipAString( "ks" ); material.specular = readAFloat(); skipAString( "exp" ); material.hilight = readAFloat(); skipAString( "ior" ); material.refraction = readAFloat(); // Environment map if ( skipAString("environment:" ) ) { size_t len = readALong(); // file name length m_bufPos += len; // skip environment file name skipAString( "flags" ); readALong(); // skip flags } // Texture map if ( skipAString("texture:" ) ) { size_t len = readALong(); // file name length std::string path; path.assign( (char *) m_bufPos, len ); m_bufPos += len; // scan past filename replaceBackslash( path ); std::string file = getFileNameFromPath( path.c_str() ); std::string newPath = m_modelPath + "/"; log_debug( "texture filename is '%s'\n", file.c_str() ); material.texFile = newPath + fixFileCase( newPath.c_str(), file.c_str() ); skipAString( "offset" ); material.uOffset = readAFloat(); skipAString( "," ); material.vOffset = readAFloat(); skipAString( "repeats" ); material.uRepeat = readAFloat(); skipAString( "," ); material.vRepeat = readAFloat(); skipAString( "flags" ); readAFloat(); // flags, ignored } // Bump map ignored return true; } bool CobFilter::readAUnknownChunk( const CobFilter::ChunkHeaderT & header ) { //log_debug( "skipping unknown chunk %s of %d bytes\n", header.chunkChars, header.length ); m_bufPos = m_chunkEnd; return true; } //------------------------------------------------------------------ // Binary read functions int32_t CobFilter::readBLong() { uint32_t rval = *((uint32_t *) m_bufPos); m_bufPos += sizeof( rval ); rval = ltoh_u32( rval ); return rval; } int16_t CobFilter::readBShort() { uint16_t rval = *((uint16_t *) m_bufPos); m_bufPos += sizeof( rval ); rval = ltoh_u16( rval ); return rval; } char CobFilter::readBChar() { char rval = *((char *) m_bufPos); m_bufPos += sizeof( rval ); return rval; } float CobFilter::readBFloat() { float rval = *((float *) m_bufPos); m_bufPos += sizeof( rval ); rval = ltoh_float( rval ); return rval; } bool CobFilter::readBString( std::string & str ) { log_debug( "reading string at %p\n", m_bufPos ); log_debug( "value is %02x %02x\n", m_bufPos[0], m_bufPos[1] ); size_t len = readBShort(); log_debug( "strlen is %d at %p\n", len, m_bufPos ); str.assign( (char *) m_bufPos, len ); m_bufPos += len; log_debug( "done reading string '%s' at %p\n", str.c_str(), m_bufPos ); return true; } bool CobFilter::readBName( std::string & str ) { readBShort(); // dup count, ignored readBString( str ); return true; } bool CobFilter::readBLocalAxes( CobFilter::LocalAxesT & axes ) { int i = 0; for ( i = 0; i < 3; i++ ) { axes.center[i] = readBFloat(); } for ( i = 0; i < 3; i++ ) { axes.xAxis[i] = readBFloat(); } for ( i = 0; i < 3; i++ ) { axes.yAxis[i] = readBFloat(); } for ( i = 0; i < 3; i++ ) { axes.zAxis[i] = readBFloat(); } return true; } bool CobFilter::readBCurrentPosition( CobFilter::CurrentPositionT & pos ) { int r = 0; int c = 0; for ( r = 0; r < 3; r++ ) { for ( c = 0; c < 4; c++ ) { pos.mat[r][c] = readBFloat(); } } return true; } bool CobFilter::readBChunkHeader( CobFilter::ChunkHeaderT & header ) { strncpy( header.chunkChars, (char*) m_bufPos, 4 ); header.chunkChars[4] = '\0'; m_bufPos += 4; header.type = chunkCharsToType( header.chunkChars ); if ( header.type == CT_EOF ) { return true; // We're done } header.majorVersion = readBShort(); header.minorVersion = readBShort(); header.chunkId = readBLong(); header.parentId = readBLong(); header.length = readBLong(); return true; } bool CobFilter::readBPolygonChunk( const CobFilter::ChunkHeaderT & header, CobFilter::PolygonMeshT & mesh ) { // Versions 0.2 through 0.5 are identical // Version 0.6+ adds additional flags // // Name // Local Axes // Current Position // Local Vertex List // UV Vertex List // Face List // Additional Flags (0.6+) readBName( mesh.name ); log_debug( "poly chunk name is %s\n", mesh.name.c_str() ); readBLocalAxes( mesh.localAxes ); readBCurrentPosition( mesh.currentPosition ); Matrix m; mesh.currentPosition.toMatrix( m ); fflush( stdout ); // Vertices size_t vcount = readBLong(); log_debug( "reading %d vertices\n", vcount ); for ( size_t v = 0; v < vcount; v++ ) { double coord[4]; coord[0] = readBFloat(); coord[1] = readBFloat(); coord[2] = readBFloat(); coord[3] = 1.0; m.apply( coord ); VertexT vert; vert.coord[0] = coord[0]; vert.coord[1] = coord[1]; vert.coord[2] = coord[2]; mesh.vertexList.push_back( vert ); } // UV Coordinates size_t uvcount = readBLong(); log_debug( "reading %d texture coordiantes\n", uvcount ); TextureCoordT tc; for ( size_t uv = 0; uv < uvcount; uv++ ) { tc.u = readBFloat(); tc.v = readBFloat(); mesh.uvList.push_back( tc ); } // Faces size_t fcount = readBLong(); log_debug( "reading %d faces\n", fcount ); for ( size_t f = 0; f < fcount; f++ ) { PolygonFaceT face; face.flags = readBChar(); size_t vcount = readBShort(); if ( (face.flags & FF_HOLE) == 0 ) { face.matNumber = readBShort(); PolygonVertexT pv; size_t v = 0; for ( v = 0; v < vcount; v++ ) { pv.vertex = readBLong(); pv.uvCoord = readBLong(); face.faceVertices.push_back( pv ); } } else { log_warning( "skipping %d vertices in hole\n", vcount ); // HOLE faces are not supported, ignore them m_bufPos += vcount * 8; // Each hole vertex is 8 bytes } mesh.faceList.push_back( face ); } return true; } bool CobFilter::readBMaterialChunk( const CobFilter::ChunkHeaderT & header, CobFilter::MaterialT & material ) { material.matNumber = readBShort(); material.shaderType = readBChar(); material.facetType = readBChar(); material.facetAngle = readBChar(); if ( material.facetType == 's' ) { material.facetAngle = 180; } else if ( material.facetType == 'f' ) { material.facetAngle = 0; } material.red = readBFloat(); material.green = readBFloat(); material.blue = readBFloat(); material.alpha = readBFloat(); material.ambient = readBFloat(); material.specular = readBFloat(); material.hilight = readBFloat(); material.refraction = readBFloat(); // Environment map (skip) if ( strncmp( (char *) m_bufPos, "e:", 2 ) == 0 ) { m_bufPos += 3; // skip environment identifier and flags std::string path = ""; readBString( path ); } // Texture map if ( strncmp( (char *) m_bufPos, "t:", 2 ) == 0 ) { m_bufPos += 2; // skip texture identifier readBChar(); // ignore flags std::string path = ""; readBString( path ); replaceBackslash( path ); std::string file = getFileNameFromPath( path.c_str() ); log_debug( "texture filename is '%s'\n", file.c_str() ); std::string newPath = m_modelPath + std::string("/"); material.texFile = newPath + fixFileCase( newPath.c_str(), file.c_str() ); material.uOffset = readBFloat(); material.vOffset = readBFloat(); material.uRepeat = readBFloat(); material.vRepeat = readBFloat(); } // Bump map (skip) if ( strncmp( (char *) m_bufPos, "b:", 2 ) == 0 ) { m_bufPos += 2; // skip bump map identifier and flags std::string path = ""; readBString( path ); readBFloat(); // U Offset readBFloat(); // V Offset readBFloat(); // U Repeat readBFloat(); // V Repeat readBFloat(); // Amplitude } return true; } bool CobFilter::readBUnknownChunk( const CobFilter::ChunkHeaderT & header ) { //log_debug( "skipping unknown chunk %s of %d bytes\n", header.chunkChars, header.length ); m_bufPos = m_chunkEnd; return true; } //------------------------------------------------------------------ // Binary write functions void CobFilter::writeBLong( int32_t val ) { int32_t writeVal = htol_u32( val ); fwrite( &writeVal, sizeof(writeVal), 1, m_fp ); } void CobFilter::writeBShort( int16_t val ) { int16_t writeVal = htol_u16( val ); fwrite( &writeVal, sizeof(writeVal), 1, m_fp ); } void CobFilter::writeBChar( char val ) { int8_t writeVal = (int8_t) val; fwrite( &writeVal, sizeof(writeVal), 1, m_fp ); } void CobFilter::writeBFloat( float val ) { float writeVal = htol_float( val ); fwrite( &writeVal, sizeof(writeVal), 1, m_fp ); } void CobFilter::writeBString( const std::string & str ) { size_t len = str.size(); writeBShort( (int16_t) len ); fwrite( str.c_str(), len, 1, m_fp ); } void CobFilter::writeBName( const std::string & str ) { writeBShort( 0 ); // dup count, ignored writeBString( str ); } void CobFilter::writeBStandardAxes() { int i = 0; // Center for ( i = 0; i < 3; i++ ) { writeBFloat( 0.0f ); } // X Axis writeBFloat( 1.0f ); writeBFloat( 0.0f ); writeBFloat( 0.0f ); // Y Axis writeBFloat( 0.0f ); writeBFloat( 1.0f ); writeBFloat( 0.0f ); // Z Axis writeBFloat( 0.0f ); writeBFloat( 0.0f ); writeBFloat( 1.0f ); } void CobFilter::writeBStandardPosition() { int r = 0; int c = 0; // Last row is omitted (assumed 0,0,0,1) for ( r = 0; r < 3; r++ ) { for ( c = 0; c < 4; c++ ) { writeBFloat( (c == r) ? 1.0f : 0.0f ); } } } void CobFilter::writeBChunkHeader( const CobFilter::ChunkHeaderT & header ) { switch ( header.type ) { case CT_EOF: fwrite( "END ", 4, 1, m_fp ); break; case CT_Polygon: fwrite( "PolH", 4, 1, m_fp ); break; case CT_Material: fwrite( "Mat1", 4, 1, m_fp ); break; default: log_error( "Uknown type %d, file will be corrupt\n", (int) header.type ); fwrite( "XXXX", 4, 1, m_fp ); break; } writeBShort( header.majorVersion ); writeBShort( header.minorVersion ); writeBLong( header.chunkId ); writeBLong( header.parentId ); // save offset of chunk size writeBChunkSize() can update it later m_lastChunkSizeOffset = ftell( m_fp ); writeBLong( header.length ); } void CobFilter::writeBChunkSize() { if ( m_lastChunkSizeOffset != 0 ) { size_t currentOffset = ftell( m_fp ); // Seek back to chunk size offset fseek( m_fp, m_lastChunkSizeOffset, SEEK_SET ); // Get chunk size and write it into chunk header int32_t chunkSize = currentOffset - m_lastChunkSizeOffset - sizeof(int32_t); writeBLong( chunkSize ); // Seek back to where we were in the file fseek( m_fp, currentOffset, SEEK_SET ); } } void CobFilter::writeBTriangleGroup( const std::list & triList, const std::string & constName ) { std::string name = constName; std::map vertMap; std::vector vertList; std::vector uvList; for ( size_t idx = 0; idx < name.size(); idx++ ) { if ( !isalnum( name[idx] ) ) { name[idx] = '_'; } } writeBName( name ); writeBStandardAxes(); writeBStandardPosition(); size_t tcount = triList.size(); std::list::const_iterator it; for ( it = triList.begin(); it != triList.end(); it++ ) { for ( size_t v = 0; v < 3; v++ ) { int vert = m_model->getTriangleVertex( *it, v ); if ( vertMap.find( vert ) == vertMap.end() ) { vertMap[vert] = vertList.size(); VertexT vertex; m_model->getVertexCoords( vert, vertex.coord ); vertList.push_back( vertex ); } // TODO could optimize by combining matching coords TextureCoordT uv; m_model->getTextureCoords( *it, v, uv.u, uv.v ); uvList.push_back( uv ); } } // Write local vertex count size_t vcount = vertList.size(); log_debug( "writing %d vertices for group\n", vcount ); writeBLong( vcount ); // Write local vertex positions for ( size_t v = 0; v < vcount; v++ ) { writeBFloat( vertList[v].coord[0] ); writeBFloat( vertList[v].coord[1] ); writeBFloat( vertList[v].coord[2] ); } // Write uv count size_t uvcount = uvList.size(); writeBLong( uvcount ); // Write uv data // TODO deal with out of range UVs (related to UV Offset/Repeat on Material?) for ( size_t uv = 0; uv < uvcount; uv++ ) { writeBFloat( uvList[uv].u ); writeBFloat( uvList[uv].v ); } // Write face count writeBLong( tcount ); // Write face data size_t t = 0; for ( it = triList.begin(); it != triList.end(); it++ ) { writeBChar( 0 ); writeBShort( 3 ); writeBShort( 0 ); for ( int i = 0; i < 3; i++ ) { int vert = m_model->getTriangleVertex( *it, i ); writeBLong( vertMap[ vert ] ); writeBLong( t * 3 + i ); // UV is deterministic } t++; } } void CobFilter::writeBUngrouped() { std::list triList = m_model->getUngroupedTriangles(); if ( !triList.empty() ) { ChunkHeaderT header; header.type = CT_Polygon; header.majorVersion = 0; header.minorVersion = 4; header.chunkId = getNextChunkId(); header.parentId = 0; header.length = 0; // call writeBChunkSize() when done with chunk to // correct chunk size field writeBChunkHeader( header ); writeBTriangleGroup( triList, "Ungrouped" ); // correct chunk size in header writeBChunkSize(); writeBDefaultMaterial( header.chunkId ); } } void CobFilter::writeBGrouped() { size_t gcount = m_model->getGroupCount(); for ( size_t g = 0; g < gcount; g++ ) { std::list triList = m_model->getGroupTriangles( g ); if ( !triList.empty() ) { ChunkHeaderT header; header.type = CT_Polygon; header.majorVersion = 0; header.minorVersion = 4; header.chunkId = getNextChunkId(); header.parentId = 0; header.length = 0; // call writeBChunkSize() when done with chunk to // correct chunk size field writeBChunkHeader( header ); writeBTriangleGroup( triList, m_model->getGroupName( g ) ); // correct chunk size in header writeBChunkSize(); int matId = m_model->getGroupTextureId( g ); if ( matId >= 0 ) { writeBMaterial( header.chunkId, matId, g ); } else { writeBDefaultMaterial( header.chunkId ); } } } } void CobFilter::writeBMaterial( int32_t parentId, size_t materialNumber, int groupNumber ) { if ( materialNumber < (size_t) m_model->getTextureCount() ) { ChunkHeaderT header; header.type = CT_Material; header.majorVersion = 0; header.minorVersion = 6; header.chunkId = getNextChunkId(); header.parentId = parentId; header.length = 0; // call writeBChunkSize() when done with chunk to // correct chunk size field writeBChunkHeader( header ); writeBShort( 0 ); // material index, always zero (only one material per group) writeBChar( 'p' ); // shader type int angle = m_model->getGroupAngle( groupNumber ); if ( angle > 0 ) { if ( angle > 179 ) { angle = 179; } writeBChar( 'a' ); writeBChar( (char) angle ); } else { writeBChar( 'f' ); writeBChar( 0 ); } // Color float fcolor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; m_model->getTextureDiffuse( materialNumber, fcolor ); writeBFloat( fcolor[0] ); // red writeBFloat( fcolor[1] ); // green writeBFloat( fcolor[2] ); // blue writeBFloat( fcolor[3] ); // alpha // Co-efficients float fval[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; float coeff = 0.0f; // Ambient co-efficient m_model->getTextureAmbient( materialNumber, fval ); coeff = _valToCoeff( fval ); writeBFloat( coeff ); // Specular co-efficient m_model->getTextureSpecular( materialNumber, fval ); coeff = _valToCoeff( fval ); writeBFloat( coeff ); // Hilight co-efficient writeBFloat( 0.0f ); // Index of refraction writeBFloat( 1.0f ); // write texture filename if exists if ( m_model->getMaterialType( materialNumber ) == Model::Material::MATTYPE_TEXTURE ) { fwrite( "t:", 2, 1, m_fp ); writeBChar( 0x02 ); std::string texFile = m_model->getTextureFilename( materialNumber ); texFile = getFileNameFromPath( texFile.c_str() ); writeBString( texFile ); // TODO make sure these are handled correctly writeBFloat( 0.0 ); // U Offset writeBFloat( 0.0 ); // V Offset writeBFloat( 1.0 ); // U Repeat writeBFloat( 1.0 ); // V Repeat } // correct chunk size in header writeBChunkSize(); } else { writeBDefaultMaterial( parentId ); } } void CobFilter::writeBDefaultMaterial( int32_t parentId ) { ChunkHeaderT header; header.type = CT_Material; header.majorVersion = 0; header.minorVersion = 6; header.chunkId = getNextChunkId(); header.parentId = parentId; header.length = 0; // call writeBChunkSize() when done with chunk to // correct chunk size field writeBChunkHeader( header ); writeBShort( 0 ); // material index, always zero (only one material per group) writeBChar( 'p' ); // shader type writeBChar( 's' ); // facet type writeBChar( 32 ); // autofacet angle // Color writeBFloat( 1.0f ); // red writeBFloat( 1.0f ); // green writeBFloat( 1.0f ); // blue writeBFloat( 1.0f ); // alpha // Ambient co-efficient writeBFloat( 0.0f ); // Specular co-efficient writeBFloat( 0.0f ); // Hilight co-efficient writeBFloat( 0.0f ); // Index of refraction writeBFloat( 1.0f ); // correct chunk size in header writeBChunkSize(); } void CobFilter::writeBEOF() { ChunkHeaderT header; header.type = CT_EOF; header.majorVersion = 1; header.minorVersion = 0; header.chunkId = getNextChunkId(); header.parentId = 0; header.length = 0; // call writeBChunkSize() when done with chunk to // correct chunk size field writeBChunkHeader( header ); // correct chunk size in header writeBChunkSize(); } #ifdef PLUGIN //------------------------------------------------------------------ // Plugin functions //------------------------------------------------------------------ extern "C" bool plugin_init() { if ( s_filter == NULL ) { s_filter = new CobFilter(); FilterManager * texmgr = FilterManager::getInstance(); texmgr->registerFilter( s_filter ); } log_debug( "COB model filter plugin initialized\n" ); return true; } // The filter manager will delete our registered filter. // We have no other cleanup to do extern "C" bool plugin_uninit() { s_filter = NULL; // FilterManager deletes filters log_debug( "COB model filter plugin uninitialized\n" ); return true; } extern "C" const char * plugin_version() { return "0.1.0"; } extern "C" const char * plugin_desc() { return "COB model filter"; } #endif // PLUGIN mm3d-1.3.7/src/libmm3d/texture.cc0000644000175000017500000001060510744511346013437 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "texture.h" #include "translate.h" int Texture::s_allocated = 0; #include #include Texture::Texture() : m_name( NULL ), m_filename( NULL ), m_isBad( false ), m_height( 0 ), m_width( 0 ), m_format( FORMAT_RGBA ), m_data( NULL ) { s_allocated++; } Texture::~Texture() { if ( m_name ) { free( m_name ); } if ( m_filename ) { free( m_filename ); } if ( m_data ) { delete[] m_data; } s_allocated--; } bool Texture::compare( Texture * t1, Texture * t2, CompareResultT * res, unsigned fuzzyValue ) { return t1->compare( t2, res, fuzzyValue ); } bool Texture::compare( Texture * tex, CompareResultT * res, unsigned fuzzyValue ) { Texture * t1 = this; Texture * t2 = tex; if ( t1->m_width != t2->m_width || t1->m_height != t2->m_height || t1->m_format != t2->m_format || t1->m_isBad || t2->m_isBad ) { res->comparable = false; return false; } res->comparable = true; bool hasAlpha = (t1->m_format == Texture::FORMAT_RGBA) ? true : false; unsigned count = t1->m_width * t1->m_height; res->pixelCount = count; res->matchCount = 0; res->fuzzyCount = 0; unsigned bytespp = hasAlpha ? 4 : 3; unsigned off = 0; unsigned fuzzy = 0; for ( unsigned p = 0; p < count; p++ ) { off = p * bytespp; fuzzy = 0; fuzzy += abs(t1->m_data[ off + 0 ] - t2->m_data[ off + 0 ]); fuzzy += abs(t1->m_data[ off + 1 ] - t2->m_data[ off + 1 ]); fuzzy += abs(t1->m_data[ off + 2 ] - t2->m_data[ off + 2 ]); if ( hasAlpha ) { fuzzy += abs(t1->m_data[ off + 3 ] - t2->m_data[ off + 3 ]); } if ( hasAlpha && t1->m_data[ off + 3 ] == 0 && t2->m_data[ off + 3 ] == 0 ) { fuzzy = 0; } if ( fuzzy == 0 ) res->matchCount++; if ( fuzzy <= fuzzyValue ) res->fuzzyCount++; } return( res->pixelCount == res->matchCount ); } const char * Texture::errorToString( Texture::ErrorE e ) { switch ( e ) { case ERROR_NONE: return QT_TRANSLATE_NOOP( "LowLevel", "Success" ); case ERROR_NO_FILE: return QT_TRANSLATE_NOOP( "LowLevel", "File does not exist" ); case ERROR_NO_ACCESS: return QT_TRANSLATE_NOOP( "LowLevel", "Permission denied" ); case ERROR_FILE_OPEN: return QT_TRANSLATE_NOOP( "LowLevel", "Could not open file" ); case ERROR_FILE_READ: return QT_TRANSLATE_NOOP( "LowLevel", "Could not read from file" ); case ERROR_FILE_WRITE: return QT_TRANSLATE_NOOP( "LowLevel", "Could not write file" ); case ERROR_BAD_MAGIC: return QT_TRANSLATE_NOOP( "LowLevel", "File is the wrong type or corrupted" ); case ERROR_UNSUPPORTED_VERSION: return QT_TRANSLATE_NOOP( "LowLevel", "Unsupported version" ); case ERROR_BAD_DATA: return QT_TRANSLATE_NOOP( "LowLevel", "File contains invalid data" ); case ERROR_UNEXPECTED_EOF: return QT_TRANSLATE_NOOP( "LowLevel", "Unexpected end of file" ); case ERROR_UNSUPPORTED_OPERATION: return QT_TRANSLATE_NOOP( "LowLevel", "This operation is not supported" ); case ERROR_BAD_ARGUMENT: return QT_TRANSLATE_NOOP( "LowLevel", "Invalid argument (internal error, probably null pointer argument)" ); case ERROR_UNKNOWN: return QT_TRANSLATE_NOOP( "LowLevel", "Unknown error" ); default: break; } return QT_TRANSLATE_NOOP( "LowLevel", "Invalid error code" ); } mm3d-1.3.7/src/libmm3d/model_influence.cc0000644000175000017500000005210511000471707015060 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "log.h" #ifdef MM3D_EDIT #include "modelstatus.h" #include "undomgr.h" #include "modelundo.h" #endif // MM3D_EDIT #include #include #include #include #include #include #include bool Model::setPositionBoneJoint( const Position & pos, int joint ) { removeAllPositionInfluences( pos ); if ( joint >= 0 ) { return addPositionInfluence( pos, joint, IT_Custom, 1.0 ); } return false; } bool Model::setVertexBoneJoint( unsigned vertex, int joint ) { removeAllVertexInfluences( vertex ); if ( joint >= 0 ) { return addVertexInfluence( vertex, joint, IT_Custom, 1.0 ); } return false; } bool Model::setPointBoneJoint( unsigned point, int joint ) { removeAllPointInfluences( point ); if ( joint >= 0 ) { return addPointInfluence( point, joint, IT_Custom, 1.0 ); } return false; } list Model::getBoneJointVertices( int joint ) const { list rval; if ( joint >= -1 && joint < (signed) m_joints.size() ) { InfluenceList ilist; InfluenceList::iterator it; for ( unsigned v = 0; v < m_vertices.size(); v++ ) { getVertexInfluences( v, ilist ); for ( it = ilist.begin(); it != ilist.end(); it++ ) { if ( (*it).m_boneId == joint ) { rval.push_back( v ); break; } } } } return rval; } bool Model::addPositionInfluence( const Position & pos, unsigned joint, InfluenceTypeE type, double weight ) { switch ( pos.type ) { case PT_Vertex: return addVertexInfluence( pos.index, joint, type, weight ); case PT_Point: return addPointInfluence( pos.index, joint, type, weight ); default: break; } return false; } bool Model::addVertexInfluence( unsigned vertex, unsigned joint, InfluenceTypeE type, double weight ) { if ( vertex < m_vertices.size() && joint < m_joints.size() ) { m_changeBits |= AddOther; Vertex * v = m_vertices[ vertex ]; InfluenceList::iterator it; for ( it = v->m_influences.begin(); it != v->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { InfluenceT oldInf = (*it); (*it).m_weight = weight; (*it).m_type = type; InfluenceT newInf = (*it); MU_UpdatePositionInfluence * undo = new MU_UpdatePositionInfluence(); Position pos; pos.type = PT_Vertex; pos.index = vertex; undo->updatePositionInfluence( pos, newInf, oldInf ); sendUndo( undo ); calculateRemainderWeight( v->m_influences ); return true; } } InfluenceT inf; inf.m_boneId = (int) joint; inf.m_weight = weight; inf.m_type = type; if ( v->m_influences.size() < MAX_INFLUENCES ) { MU_SetPositionInfluence * undo = new MU_SetPositionInfluence(); Position pos; pos.type = PT_Vertex; pos.index = vertex; undo->setPositionInfluence( true, pos, v->m_influences.size(), inf ); sendUndo( undo ); v->m_influences.push_back( inf ); calculateRemainderWeight( v->m_influences ); return true; } } return false; } bool Model::addPointInfluence( unsigned point, unsigned joint, InfluenceTypeE type, double weight ) { if ( point < m_points.size() && joint < m_joints.size() ) { m_changeBits |= AddOther; Point * p = m_points[ point ]; InfluenceList::iterator it; for ( it = p->m_influences.begin(); it != p->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { InfluenceT oldInf = (*it); (*it).m_weight = weight; (*it).m_type = type; InfluenceT newInf = (*it); MU_UpdatePositionInfluence * undo = new MU_UpdatePositionInfluence(); Position pos; pos.type = PT_Point; pos.index = point; undo->updatePositionInfluence( pos, newInf, oldInf ); sendUndo( undo ); calculateRemainderWeight( p->m_influences ); return true; } } InfluenceT inf; inf.m_boneId = (int) joint; inf.m_weight = weight; inf.m_type = type; if ( p->m_influences.size() < MAX_INFLUENCES ) { MU_SetPositionInfluence * undo = new MU_SetPositionInfluence(); Position pos; pos.type = PT_Point; pos.index = point; undo->setPositionInfluence( true, pos, p->m_influences.size(), inf ); sendUndo( undo ); p->m_influences.push_back( inf ); calculateRemainderWeight( p->m_influences ); return true; } } return false; } bool Model::removePositionInfluence( const Position & pos, unsigned joint ) { switch ( pos.type ) { case PT_Vertex: return removeVertexInfluence( pos.index, joint ); case PT_Point: return removePointInfluence( pos.index, joint ); default: break; } return false; } bool Model::removeVertexInfluence( unsigned vertex, unsigned joint ) { if ( vertex < m_vertices.size() ) { m_changeBits |= AddOther; Vertex * v = m_vertices[ vertex ]; InfluenceList::iterator it; int count = 0; for ( it = v->m_influences.begin(); it != v->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { MU_SetPositionInfluence * undo = new MU_SetPositionInfluence(); Position pos; pos.type = PT_Vertex; pos.index = vertex; undo->setPositionInfluence( false, pos, count, *it ); sendUndo( undo ); v->m_influences.erase( it ); calculateRemainderWeight( v->m_influences ); return true; } count++; } } return false; } bool Model::removePointInfluence( unsigned point, unsigned joint ) { if ( point < m_points.size() ) { m_changeBits |= AddOther; Point * p = m_points[ point ]; InfluenceList::iterator it; int count = 0; for ( it = p->m_influences.begin(); it != p->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { MU_SetPositionInfluence * undo = new MU_SetPositionInfluence(); Position pos; pos.type = PT_Point; pos.index = point; undo->setPositionInfluence( false, pos, count, *it ); sendUndo( undo ); p->m_influences.erase( it ); calculateRemainderWeight( p->m_influences ); return true; } count++; } } return false; } bool Model::removeAllPositionInfluences( const Position & pos ) { switch ( pos.type ) { case PT_Vertex: return removeAllVertexInfluences( pos.index ); case PT_Point: return removeAllPointInfluences( pos.index ); default: break; } return false; } bool Model::removeAllVertexInfluences( unsigned vertex ) { if ( vertex < m_vertices.size() ) { InfluenceList & l = m_vertices[ vertex ]->m_influences; while ( !l.empty() ) { Position pos; pos.type = PT_Vertex; pos.index = vertex; removePositionInfluence( pos, l.back().m_boneId ); } return true; } return false; } bool Model::removeAllPointInfluences( unsigned point ) { if ( point < m_points.size() ) { InfluenceList & l = m_points[ point ]->m_influences; while ( !l.empty() ) { Position pos; pos.type = PT_Point; pos.index = point; removePositionInfluence( pos, l.back().m_boneId ); } return true; } return false; } bool Model::getPositionInfluences( const Position & pos, InfluenceList & l ) const { switch ( pos.type ) { case PT_Vertex: return getVertexInfluences( pos.index, l ); case PT_Point: return getPointInfluences( pos.index, l ); default: break; } return false; } bool Model::getVertexInfluences( unsigned vertex, InfluenceList & l ) const { if ( vertex < m_vertices.size() ) { l = m_vertices[ vertex ]->m_influences; return true; } return false; } bool Model::getPointInfluences( unsigned point, InfluenceList & l ) const { if ( point < m_points.size() ) { l = m_points[ point ]->m_influences; return true; } return false; } int Model::getPrimaryPositionInfluence( const Position & pos ) const { InfluenceList l; getPositionInfluences( pos, l ); Model::InfluenceT inf; inf.m_boneId = -1; inf.m_weight = -1.0; InfluenceList::iterator it; for ( it = l.begin(); it != l.end(); it++ ) { if ( inf < *it ) { inf = *it; } } return inf.m_boneId; } int Model::getPrimaryVertexInfluence( unsigned vertex ) const { Position pos; pos.type = PT_Vertex; pos.index = vertex; return getPrimaryPositionInfluence( pos ); } int Model::getPrimaryPointInfluence( unsigned point ) const { Position pos; pos.type = PT_Point; pos.index = point; return getPrimaryPositionInfluence( pos ); } bool Model::setPositionInfluenceType( const Position & pos, unsigned int joint, InfluenceTypeE type ) { switch ( pos.type ) { case PT_Vertex: return setVertexInfluenceType( pos.index, joint, type ); case PT_Point: return setPointInfluenceType( pos.index, joint, type ); default: break; } return false; } bool Model::setVertexInfluenceType( unsigned vertex, unsigned int joint, InfluenceTypeE type ) { if ( vertex < m_vertices.size() && joint < m_joints.size() ) { m_changeBits |= AddOther; Vertex * v = m_vertices[ vertex ]; InfluenceList::iterator it; for ( it = v->m_influences.begin(); it != v->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { InfluenceT oldInf = (*it); (*it).m_type = type; InfluenceT newInf = (*it); MU_UpdatePositionInfluence * undo = new MU_UpdatePositionInfluence(); Position pos; pos.type = PT_Vertex; pos.index = vertex; undo->updatePositionInfluence( pos, newInf, oldInf ); sendUndo( undo ); calculateRemainderWeight( v->m_influences ); return true; } } } return false; } bool Model::setPointInfluenceType( unsigned point, unsigned int joint, InfluenceTypeE type ) { if ( point < m_points.size() && joint < m_joints.size() ) { m_changeBits |= AddOther; Point * p = m_points[ point ]; InfluenceList::iterator it; for ( it = p->m_influences.begin(); it != p->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { InfluenceT oldInf = (*it); (*it).m_type = type; InfluenceT newInf = (*it); MU_UpdatePositionInfluence * undo = new MU_UpdatePositionInfluence(); Position pos; pos.type = PT_Point; pos.index = point; undo->updatePositionInfluence( pos, newInf, oldInf ); sendUndo( undo ); calculateRemainderWeight( p->m_influences ); return true; } } } return false; } bool Model::setPositionInfluenceWeight( const Position & pos, unsigned int joint, double weight ) { switch ( pos.type ) { case PT_Vertex: return setVertexInfluenceWeight( pos.index, joint, weight ); case PT_Point: return setPointInfluenceWeight( pos.index, joint, weight ); default: break; } return false; } bool Model::setVertexInfluenceWeight( unsigned vertex, unsigned int joint, double weight ) { if ( vertex < m_vertices.size() && joint < m_joints.size() ) { m_changeBits |= AddOther; Vertex * v = m_vertices[ vertex ]; InfluenceList::iterator it; for ( it = v->m_influences.begin(); it != v->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { InfluenceT oldInf = (*it); (*it).m_weight = weight; InfluenceT newInf = (*it); MU_UpdatePositionInfluence * undo = new MU_UpdatePositionInfluence(); Position pos; pos.type = PT_Vertex; pos.index = vertex; undo->updatePositionInfluence( pos, newInf, oldInf ); sendUndo( undo ); calculateRemainderWeight( v->m_influences ); return true; } } } return false; } bool Model::setPointInfluenceWeight( unsigned point, unsigned int joint, double weight ) { if ( point < m_points.size() && joint < m_joints.size() ) { m_changeBits |= AddOther; Point * p = m_points[ point ]; InfluenceList::iterator it; for ( it = p->m_influences.begin(); it != p->m_influences.end(); it++ ) { if ( (*it).m_boneId == (int) joint ) { InfluenceT oldInf = (*it); (*it).m_weight = weight; InfluenceT newInf = (*it); MU_UpdatePositionInfluence * undo = new MU_UpdatePositionInfluence(); Position pos; pos.type = PT_Point; pos.index = point; undo->updatePositionInfluence( pos, newInf, oldInf ); sendUndo( undo ); calculateRemainderWeight( p->m_influences ); return true; } } } return false; } double Model::calculatePositionInfluenceWeight( const Position & pos, unsigned joint ) const { switch ( pos.type ) { case PT_Vertex: return calculateVertexInfluenceWeight( pos.index, joint ); case PT_Point: return calculatePointInfluenceWeight( pos.index, joint ); default: break; } return 0.0; } double Model::calculateVertexInfluenceWeight( unsigned vertex, unsigned joint ) const { double coord[3] = { 0, 0, 0 }; getVertexCoords( vertex, coord ); return calculateCoordInfluenceWeight( coord, joint ); } double Model::calculatePointInfluenceWeight( unsigned point, unsigned joint ) const { double coord[3] = { 0, 0, 0 }; getPointCoords( point, coord ); return calculateCoordInfluenceWeight( coord, joint ); } double Model::calculateCoordInfluenceWeight( const double * coord, unsigned joint ) const { if ( joint >= m_joints.size() ) { return 0.0; } int bcount = m_joints.size(); int child = -1; double cdist = 0.0; for ( int b = 0; b < bcount; b++ ) { if ( getBoneJointParent( b ) == (int) joint ) { double ccoord[3]; getBoneJointCoords( b, ccoord ); double d = distance( ccoord, coord ); if ( child < 0 || d < cdist ) { child = b; cdist = d; } } } double bvec[3] = { 0, 0, 0 }; double pvec[3] = { 0, 0, 0 }; getBoneVector( joint, bvec, coord ); double jcoord[3] = { 0, 0, 0 }; getBoneJointCoords( joint, jcoord ); pvec[0] = coord[0] - jcoord[0]; pvec[1] = coord[1] - jcoord[1]; pvec[2] = coord[2] - jcoord[2]; normalize3( pvec ); // get cos from point to bone vector double bcos = dot3( pvec, bvec ); bcos = (bcos + 1.0) / 2.0; if ( child < 0 ) { // no children return bcos; } double cvec[3] = { 0, 0, 0 }; getBoneVector( child, cvec, coord ); // get cos from point to child vector double ccoord[3] = { 0, 0, 0 }; getBoneJointCoords( child, ccoord ); pvec[0] = coord[0] - ccoord[0]; pvec[1] = coord[1] - ccoord[1]; pvec[2] = coord[2] - ccoord[2]; normalize3( pvec ); double ccos = dot3( pvec, cvec ); ccos = -ccos; ccos = (ccos + 1.0) / 2.0; return bcos * ccos; } bool Model::autoSetPositionInfluences( const Position & pos, double sensitivity, bool selected ) { switch ( pos.type ) { case PT_Vertex: return autoSetVertexInfluences( pos.index, sensitivity, selected ); case PT_Point: return autoSetPointInfluences( pos.index, sensitivity, selected ); default: break; } return false; } bool Model::autoSetVertexInfluences( unsigned vertex, double sensitivity, bool selected ) { double coord[3] = { 0, 0, 0 }; getVertexCoords( vertex, coord ); std::list l; if ( autoSetCoordInfluences( coord, sensitivity, selected, l ) ) { removeAllVertexInfluences( vertex ); std::list::iterator it; for ( it = l.begin(); it != l.end(); it++ ) { double w = calculateVertexInfluenceWeight( vertex, *it ); addVertexInfluence( vertex, *it, Model::IT_Auto, w ); } return true; } return false; } bool Model::autoSetPointInfluences( unsigned point, double sensitivity, bool selected ) { double coord[3] = { 0, 0, 0 }; getPointCoords( point, coord ); std::list l; if ( autoSetCoordInfluences( coord, sensitivity, selected, l ) ) { removeAllPointInfluences( point ); std::list::iterator it; for ( it = l.begin(); it != l.end(); it++ ) { double w = calculatePointInfluenceWeight( point, *it ); addPointInfluence( point, *it, Model::IT_Auto, w ); } return true; } return false; } bool Model::autoSetCoordInfluences( double * coord, double sensitivity, bool selected, std::list & infList ) { int bcount = m_joints.size(); if ( bcount <= 0 ) { return false; } int bestJoint = -1; int bestChild = -1; double bestChildDist = 0; double bestDist = 0; double bestDot = 0; for ( int joint = 0; joint < bcount; joint++ ) { if ( !selected || m_joints[ joint ]->m_selected ) { int child = -1; double cdist = 0.0; for ( int b = 0; b < bcount; b++ ) { if ( getBoneJointParent( b ) == (int) joint ) { double ccoord[3]; getBoneJointCoords( b, ccoord ); double d = distance( ccoord, coord ); if ( child < 0 || d < cdist ) { child = b; cdist = d; } } } double bvec[3] = { 0, 0, 0 }; double pvec[3] = { 0, 0, 0 }; getBoneVector( joint, bvec, coord ); double jcoord[3] = { 0, 0, 0 }; getBoneJointCoords( joint, jcoord ); pvec[0] = coord[0] - jcoord[0]; pvec[1] = coord[1] - jcoord[1]; pvec[2] = coord[2] - jcoord[2]; normalize3( pvec ); double dist = distance( coord, jcoord ); // get cos from point to bone vector double bcos = dot3( pvec, bvec ); if ( bcos > 0.0 ) { dist *= 0.667;// *= bcos; } else { dist *= 2.0; } if ( bestJoint < 0 || dist < bestDist ) { bestJoint = joint; bestDist = dist; bestChild = child; bestChildDist = cdist; bestDot = bcos; } } } if ( bestJoint >= 0 ) { infList.push_back( bestJoint ); if ( bestChild >= 0 ) { if ( (bestChildDist * (1.0 - sensitivity)) < (bestDist * 0.5) ) { infList.push_back( bestChild ); } } int parent = getBoneJointParent( bestJoint ); if ( parent > 0 ) { if ( ((bestDot - 1.0)) * sensitivity < -0.080 ) { infList.push_back( parent ); } } return true; } return false; } void Model::calculateRemainderWeight( Model::InfluenceList & list ) const { int remainders = 0; double remaining = 1.0; InfluenceList::iterator it; for ( it = list.begin(); remaining > 0 && it != list.end(); it++ ) { if ( (*it).m_type == IT_Remainder ) { remainders++; } else { remaining -= (*it).m_weight; } } if ( remainders > 0 && remaining > 0 ) { for ( it = list.begin(); it != list.end(); it++ ) { if ( (*it).m_type == IT_Remainder ) { (*it).m_weight = remaining / (double) remainders; } } } } mm3d-1.3.7/src/libmm3d/mm3dfilter.cc0000644000175000017500000027026511025050654014010 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "mm3dfilter.h" #include "model.h" #include "filedatadest.h" #include "filedatasource.h" #include "texture.h" #include "log.h" #include "binutil.h" #include "misc.h" #include "endianconfig.h" #include "mm3dport.h" #include "msg.h" #include "translate.h" #include "file_closer.h" #include #include #include #include #include using std::list; using std::string; template class FunctionCaller { public: FunctionCaller( T * obj, void (T::*method)(void) ) { m_obj = obj; m_method = method; } ~FunctionCaller() { (m_obj->*m_method)(); } private: T * m_obj; void (T::*m_method)(void); }; const char MisfitFilter::MAGIC[] = "MISFIT3D"; const uint8_t MisfitFilter::WRITE_VERSION_MAJOR = 0x01; const uint8_t MisfitFilter::WRITE_VERSION_MINOR = 0x05; // FIXME bump version const uint16_t MisfitFilter::OFFSET_TYPE_MASK = 0x3fff; const uint16_t MisfitFilter::OFFSET_UNI_MASK = 0x8000; const uint16_t MisfitFilter::OFFSET_DIRTY_MASK = 0x4000; namespace { // Misfit MM3D format: // // File Header // // MAGIC_NUMBER 8 bytes "MISFIT3D" // MAJOR_VERSION uint8 0x01 // MINOR_VERSION uint8 0x05 // MODEL_FLAGS uint8 0x00 (reserved) // OFFSET_COUNT uint8 [offc] // // [OFFSET_COUNT] instances of: // Offset header list // OFFSET_HEADER 6 bytes * [offc] // // Offset Header // OFFSET_TYPE uint16 (highest bit 0 = Data type A, 1 = data type B) // OFFSET_VALUE uint32 // // Data header A (Variable data size) // DATA_FLAGS uint16 // DATA_COUNT uint32 // // Data block A // // [DATA_COUNT] instances of: // DATA_SIZE uint32 bytes // DATA_BLOCK_A [DATA_SIZE] bytes // // Data header B (Uniform data size) // DATA_FLAGS uint16 // DATA_COUNT uint32 // DATA_SIZE uint32 // // Data block B // // [DATA_COUNT] instances of: // DATA_BLOCK_B [DATA_SIZE] bytes // // // Offset A types: // 0x1001 Meta information // 0x1002 Unknown type information // 0x0101 Groups // 0x0141 Embedded textures // 0x0142 External textures // 0x0161 Materials // 0x016c Texture Projection Triangles // 0x0191 Canvas background images // // 0x0301 Skeletal Animations // 0x0321 Frame Animations // 0x0326 Frame Animation Points // 0x0341 Frame Relative Animations // // Offset B types: // 0x0001 Vertices // 0x0021 Triangles // 0x0026 Triangle Normals // 0x0041 Joints // 0x0046 Joint Vertices // 0x0061 Points // 0x0106 Smooth Angles // 0x0168 Texture Projections // 0x0121 Texture Coordinates // // // // Meta information data // KEY ASCIIZ <= 1024 (may not be empty) // VALUE ASCIIZ <= 1024 (may be empty) // // Unknown type information // OFFSET_TYPE uint16 // INFO_STRING ASCIIZ <= 256 (inform user how to support this data) // // // Vertex data // FLAGS uint16 // X_COORD float32 // Y_COORD float32 // Z_COORD float32 // // // Triangle data // FLAGS uint16 // VERTEX1_INDEX uint32 // VERTEX2_INDEX uint32 // VERTEX3_INDEX uint32 // // Group data // FLAGS uint16 // NAME ASCIIZ <= inf // TRI_COUNT uint32 // TRI_INDICES uint32 * [TRI_COUNT] // SMOOTHNESS uint8 // MATERIAL_INDEX uint32 // // Smooth Angles (maximum angle between smoothed normals for a group) // GROUP_INDEX uint32 // SMOOTHNESS uint8 // // Weighted Influences // POS_TYPE uint8 // POS_INDEX uint32 // INF_INDEX uint32 // INF_TYPE uint8 // INF_WEIGHT uint8 // // External texture data // FLAGS uint16 // FILENAME ASCIIZ // // Embedded texture data // FLAGS uint16 // FORMAT char8 * 4 ('JPEG', 'PNG ', 'TGA ', etc...) // TEXTURE_SIZE uint32 // DATA uint8 * [TEXTURE_SIZE] // // Material // FLAGS uint16 // TEXTURE_INDEX uint32 // NAME ASCIIZ // AMBIENT float32 * 4 // DIFFUSE float32 * 4 // SPECULAR float32 * 4 // EMISSIVE float32 * 4 // SHININESS float32 // // Projection Triangles // PROJECTION_INDEX uint32 // TRI_COUNT uint32 // TRI_INDICES uint32 * [TRI_COUNT] // // Canvas background image // FLAGS uint16 // VIEW_INDEX uint8 // SCALE float32 // CENTER_X float32 // CENTER_X float32 // CENTER_X float32 // FILENAME ASCIIZ // // Texture coordinates // FLAGS uint16 // TRI_INDEX uint32 // COORD_S float32 * 3 // COORD_T float32 * 3 // // Joint data // FLAGS uint16 // NAME char8 * 40 // PARENT_INDEX int32 // LOCAL_ROT float32 * 3 // LOCAL_TRANS float32 * 3 // // Joint Vertices // VERTEX_INDEX uint32 // JOINT_INDEX int32 // // Point data // FLAGS uint16 // NAME char8 * 40 // TYPE int32 // BONE_INDEX int32 // ROTATION float32 * 3 // TRANSLATION float32 * 3 // // Texture Projection // FLAGS uint16 // NAME char8 * 40 // TYPE int32 // POSITION float32 * 3 // UP VECTOR float32 * 3 // SEAM VECTOR float32 * 3 // U MIN float32 // V MIN float32 // U MAX float32 // V MAX float32 // // Skeletal animation // FLAGS uint16 // NAME ASCIIZ // FPS float32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // KEYFRAME_COUNT uint32 // // [KEYFRAME_COUNT] instances of: // JOINT_INDEX uint32 // KEYFRAME_TYPE uint8 (0 = rotation, 1 = translation) // PARAM float32 * 3 // // Frame animation // FLAGS uint16 // NAME ASCIIZ <= 64 // FPS float32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // // [VERTEX_COUNT] instances of: // COORD_X float32 // COORD_Y float32 // COORD_Z float32 // // Frame animation points // FLAGS uint16 // FRAME_ANIM_INDEX uint32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // // [POINT_COUNT] instances of: // ROT_X float32 // ROT_Y float32 // ROT_Z float32 // TRANS_X float32 // TRANS_Y float32 // TRANS_Z float32 // // Frame relative animation // FLAGS uint16 // NAME ASCIIZ <= 64 // FPS float32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // FVERT_COUNT uint32 // // [FVERT_COUNT] instances of: // VERTEX_INDEX // COORD_X_OFFSET float32 // COORD_Y_OFFSET float32 // COORD_Z_OFFSET float32 // typedef struct _MisfitOffset_t { uint16_t offsetType; uint32_t offsetValue; } MisfitOffsetT; typedef std::vector MisfitOffsetList; typedef enum _MisfitDataTypes_e { // A Types MDT_Meta, MDT_TypeInfo, MDT_Groups, MDT_EmbTextures, MDT_ExtTextures, MDT_Materials, MDT_ProjectionTriangles, MDT_CanvasBackgrounds, MDT_SkelAnims, MDT_FrameAnims, MDT_FrameAnimPoints, MDT_RelativeAnims, // B Types MDT_Vertices, MDT_Triangles, MDT_TriangleNormals, MDT_Joints, MDT_JointVertices, MDT_Points, MDT_SmoothAngles, MDT_WeightedInfluences, MDT_TexProjections, MDT_TexCoords, // End of list MDT_EndOfFile, MDT_MAX } MisfitDataTypesE; typedef enum _MisfitFlags_e { MF_HIDDEN = 1, // powers of 2 MF_SELECTED = 2, MF_VERTFREE = 4, // vertex does not have to be conntected to a face // Type-specific flags MF_MAT_CLAMP_S = 16, MF_MAT_CLAMP_T = 32 } MisfitFlagsE; static const uint16_t _misfitOffsetTypes[MDT_MAX] = { // Offset A types 0x1001, // Meta information 0x1002, // Unknown type information 0x0101, // Groups 0x0141, // Embedded textures 0x0142, // External textures 0x0161, // Materials 0x016c, // Texture Projection Triangles 0x0191, // Canvas background images 0x0301, // Skeletal Animations 0x0321, // Frame Animations 0x0326, // Frame Animation Points 0x0341, // Frame Relative Animations // Offset B types: 0x0001, // Vertices 0x0021, // Triangles 0x0026, // Triangle Normals 0x0041, // Joints 0x0046, // Joint Vertices 0x0061, // Points 0x0106, // Smooth Angles 0x0146, // Weighted Influences 0x0168, // Texture Projections 0x0121, // Texture Coordinates 0x3fff, // End of file }; static const char _misfitOffsetNames[MDT_MAX][30] = { // Offset A types "Meta information", "Type identity", "Groups", "Embedded textures", "External textures", "Materials", "Texture projection triangles", "Canvas background images", "Skeletal animations", "Frame animations", "Frame animation points", "Frame relative animations", // Offset B types "Vertices", "Triangles", "Triangle normals", "Joints", "Joint vertices", "Points", "Max smoothing angles", "Weighted Influences", "Texture projections", "Texture coordinates", // End of file "End of file" }; // File header struct _MM3DFILE_Header_t { char magic[8]; uint8_t versionMajor; uint8_t versionMinor; uint8_t modelFlags; uint8_t offsetCount; }; typedef struct _MM3DFILE_Header_t MM3DFILE_HeaderT; // Data header A (Variable data size) struct _MM3DFILE_DataHeaderA_t { uint16_t flags; uint32_t count; }; typedef struct _MM3DFILE_DataHeaderA_t MM3DFILE_DataHeaderAT; // Data header B (Uniform data size) struct _MM3DFILE_DataHeaderB_t { uint16_t flags; uint32_t count; uint32_t size; }; typedef struct _MM3DFILE_DataHeaderB_t MM3DFILE_DataHeaderBT; struct _MM3DFILE_Vertex_t { uint16_t flags; float32_t coord[3]; }; typedef struct _MM3DFILE_Vertex_t MM3DFILE_VertexT; const size_t FILE_VERTEX_SIZE = 14; struct _MM3DFILE_Triangle_t { uint16_t flags; uint32_t vertex[3]; }; typedef struct _MM3DFILE_Triangle_t MM3DFILE_TriangleT; const size_t FILE_TRIANGLE_SIZE = 14; struct _MM3DFILE_TriangleNormals_t { uint16_t flags; uint32_t index; float32_t normal[3][3]; }; typedef struct _MM3DFILE_TriangleNormals_t MM3DFILE_TriangleNormalsT; const size_t FILE_TRIANGLE_NORMAL_SIZE = 42; struct _MM3DFILE_Joint_t { uint16_t flags; char name[40]; int32_t parentIndex; float32_t localRot[3]; float32_t localTrans[3]; }; typedef struct _MM3DFILE_Joint_t MM3DFILE_JointT; const size_t FILE_JOINT_SIZE = 70; struct _MM3DFILE_JointVertex_t { uint32_t vertexIndex; int32_t jointIndex; }; typedef struct _MM3DFILE_JointVertex_t MM3DFILE_JointVertexT; const size_t FILE_JOINT_VERTEX_SIZE = 8; struct _MM3DFILE_WeightedInfluence_t { uint8_t posType; uint32_t posIndex; uint32_t infIndex; uint8_t infType; int8_t infWeight; }; typedef struct _MM3DFILE_WeightedInfluence_t MM3DFILE_WeightedInfluenceT; const size_t FILE_WEIGHTED_INFLUENCE_SIZE = 11; struct _MM3DFILE_Point_t { uint16_t flags; char name[40]; int32_t type; int32_t boneIndex; float32_t rot[3]; float32_t trans[3]; }; typedef struct _MM3DFILE_Point_t MM3DFILE_PointT; const size_t FILE_POINT_SIZE = 74; struct _MM3DFILE_SmoothAngle_t { uint32_t groupIndex; uint8_t angle; }; typedef struct _MM3DFILE_SmoothAngle_t MM3DFILE_SmoothAngleT; const size_t FILE_SMOOTH_ANGLE_SIZE = 5; struct _MM3DFILE_CanvasBackground_t { uint16_t flags; uint8_t viewIndex; float32_t scale; float32_t center[3]; }; typedef struct _MM3DFILE_CanvasBackground_t MM3DFILE_CanvasBackgroundT; const size_t FILE_CANVAS_BACKGROUND_SIZE = 19; struct _MM3DFILE_SkelKeyframe_t { uint32_t jointIndex; uint8_t keyframeType; float32_t param[3]; }; typedef struct _MM3DFILE_SkelKeyframe_t MM3DFILE_SkelKeyframeT; const size_t FILE_SKEL_KEYFRAME_SIZE = 17; struct _MM3DFILE_TexCoord_t { uint16_t flags; uint32_t triangleIndex; float32_t sCoord[3]; float32_t tCoord[3]; }; typedef struct _MM3DFILE_TexCoord_t MM3DFILE_TexCoordT; const size_t FILE_TEXCOORD_SIZE = 30; const size_t FILE_TEXTURE_PROJECTION_SIZE = 98; struct _UnknownData_t { uint16_t offsetType; uint32_t offsetValue; uint32_t dataLen; }; typedef struct _UnknownData_t UnknownDataT; typedef std::list UnknownDataList; static void _addOffset( MisfitDataTypesE type, bool include, MisfitOffsetList & list ) { if ( include ) { MisfitOffsetT mo; mo.offsetType = _misfitOffsetTypes[ type ]; mo.offsetValue = 0; log_debug( "adding offset type %04X\n", mo.offsetType ); list.push_back( mo ); } } static void _setOffset( MisfitDataTypesE type, uint32_t offset, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilter::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { list[n].offsetValue = offset; log_debug( "updated offset for %04X to %08X\n", list[n].offsetType, list[n].offsetValue ); break; } } } static void _setUniformOffset( MisfitDataTypesE type, bool uniform, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilter::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { if ( uniform ) { log_debug( "before uniform: %04X\n", list[n].offsetType ); list[n].offsetType |= MisfitFilter::OFFSET_UNI_MASK; log_debug( "after uniform: %04X\n", list[n].offsetType ); } else { log_debug( "before variable: %04X\n", list[n].offsetType ); list[n].offsetType &= MisfitFilter::OFFSET_TYPE_MASK; log_debug( "after variable: %04X\n", list[n].offsetType ); } break; } } } bool _offsetIncluded( MisfitDataTypesE type, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilter::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { return true; } } return false; } unsigned _offsetGet( MisfitDataTypesE type, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilter::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { return list[n].offsetValue; } } return 0; } bool _offsetIsVariable( MisfitDataTypesE type, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilter::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { return ((list[n].offsetType & MisfitFilter::OFFSET_UNI_MASK) == 0); } } return false; } } // namespace MisfitFilter::MisfitFilter() { } MisfitFilter::~MisfitFilter() { } Model::ModelErrorE MisfitFilter::readFile( Model * model, const char * const filename ) { if ( filename == NULL || filename[0] == '\0' ) { return Model::ERROR_BAD_ARGUMENT; } if ( sizeof( float32_t ) != 4 ) { msg_error( transll( QT_TRANSLATE_NOOP( "LowLevel", "MM3D encountered an unexpected data size problem\nSee Help->About to contact the developers" )).c_str() ); return Model::ERROR_FILE_OPEN; } Model::ModelErrorE err = Model::ERROR_NONE; m_src = openInput( filename, err ); FunctionCaller fc( m_src, &DataSource::close ); if ( err != Model::ERROR_NONE ) return err; string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); model->setFilename( modelFullName.c_str() ); unsigned fileLength = m_src->getFileSize(); MM3DFILE_HeaderT fileHeader; m_src->readBytes( (uint8_t *) fileHeader.magic, sizeof(fileHeader.magic) ); m_src->read( fileHeader.versionMajor ); m_src->read( fileHeader.versionMinor ); m_src->read( fileHeader.modelFlags ); m_src->read( fileHeader.offsetCount ); if ( strncmp( fileHeader.magic, MAGIC, strlen(MAGIC) ) != 0 ) { log_warning( "bad magic number file\n" ); return Model::ERROR_BAD_MAGIC; } if ( fileHeader.versionMajor != WRITE_VERSION_MAJOR ) { return Model::ERROR_UNSUPPORTED_VERSION; } unsigned offsetCount = fileHeader.offsetCount; log_debug( "Misfit file:\n" ); log_debug( " major: %d\n", fileHeader.versionMajor ); log_debug( " minor: %d\n", fileHeader.versionMinor ); log_debug( " offsets: %d\n", fileHeader.offsetCount ); log_debug( "Offset information:\n" ); unsigned t; MisfitOffsetList offsetList; unsigned lastOffset = 0; bool lastUnknown = false; UnknownDataList unknownList; for ( t = 0; t < offsetCount; t++ ) { MisfitOffsetT mo; m_src->read( mo.offsetType ); m_src->read( mo.offsetValue ); if ( mo.offsetValue < lastOffset ) { log_error( "Offset are out of order\n" ); return Model::ERROR_BAD_DATA; } if ( lastUnknown ) { unknownList.back().dataLen = mo.offsetValue - lastOffset; log_warning( "unknown data size = %d\n", unknownList.back().dataLen ); lastUnknown = false; } lastOffset = mo.offsetValue; offsetList.push_back( mo ); bool found = false; for ( unsigned e = 0; !found && e < MDT_MAX; e++ ) { if ( _misfitOffsetTypes[e] == (mo.offsetType & OFFSET_TYPE_MASK) ) { log_debug( " %08X %s\n", mo.offsetValue, _misfitOffsetNames[e] ); found = true; if ( e == MDT_EndOfFile ) { if ( mo.offsetValue != fileLength ) { if ( mo.offsetValue > fileLength ) { return Model::ERROR_UNEXPECTED_EOF; } else { log_warning( "EOF offset and file size do not match (%d and %d)\n", mo.offsetValue, fileLength ); return Model::ERROR_BAD_DATA; } } } } } if ( !found ) { log_debug( " %08X Unknown type %04X\n", mo.offsetValue, mo.offsetType ); lastUnknown = true; UnknownDataT ud; ud.offsetType = mo.offsetType; ud.offsetValue = mo.offsetValue; ud.dataLen = 0; unknownList.push_back( ud ); } } vector & modelVertices = getVertexList( model ); vector & modelTriangles = getTriangleList( model ); vector & modelGroups = getGroupList( model ); vector & modelMaterials = getMaterialList( model ); vector & modelJoints = getJointList( model ); // Used to track whether indices are valid bool missingElements = false; // Meta data if ( _offsetIncluded( MDT_Meta, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Meta, offsetList ); uint32_t offset = _offsetGet( MDT_Meta, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned m = 0; m < count; m++ ) { if ( variable ) { m_src->read( size ); } unsigned len; char key[1024]; char value[1024]; m_src->readAsciiz(key, sizeof(key) ); utf8chrtrunc( key, sizeof(key)-1 ); len = strlen(key) + 1; m_src->readAsciiz(value, sizeof(value) ); utf8chrtrunc( value, sizeof(value)-1 ); len = strlen(value) + 1; model->addMetaData( key, value ); } } // Vertices if ( _offsetIncluded( MDT_Vertices, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Vertices, offsetList ); uint32_t offset = _offsetGet( MDT_Vertices, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned v = 0; v < count; v++ ) { if ( variable ) { m_src->read( size ); } MM3DFILE_VertexT fileVert; m_src->read( fileVert.flags ); m_src->read( fileVert.coord[0] ); m_src->read( fileVert.coord[1] ); m_src->read( fileVert.coord[2] ); Model::Vertex * vert = Model::Vertex::get(); //vert->m_boneId = -1; vert->m_coord[0] = fileVert.coord[0]; vert->m_coord[1] = fileVert.coord[1]; vert->m_coord[2] = fileVert.coord[2]; uint16_t vertFlags = fileVert.flags; vert->m_selected = ((vertFlags & MF_SELECTED) == MF_SELECTED); vert->m_visible = ((vertFlags & MF_HIDDEN) != MF_HIDDEN); vert->m_free = ((vertFlags & MF_VERTFREE) == MF_VERTFREE); modelVertices.push_back( vert ); } } // Triangles if ( _offsetIncluded( MDT_Triangles, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Triangles, offsetList ); uint32_t offset = _offsetGet( MDT_Triangles, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { m_src->read( size ); } MM3DFILE_TriangleT fileTri; m_src->read( fileTri.flags ); m_src->read( fileTri.vertex[0] ); m_src->read( fileTri.vertex[1] ); m_src->read( fileTri.vertex[2] ); Model::Triangle * tri = Model::Triangle::get(); tri->m_vertexIndices[0] = fileTri.vertex[0]; tri->m_vertexIndices[1] = fileTri.vertex[1]; tri->m_vertexIndices[2] = fileTri.vertex[2]; uint16_t triFlags = fileTri.flags; tri->m_selected = ((triFlags & MF_SELECTED) == MF_SELECTED); tri->m_visible = ((triFlags & MF_HIDDEN) != MF_HIDDEN); tri->m_projection = -1; modelTriangles.push_back( tri ); } } #if 0 // Triangle Normals if ( _offsetIncluded( MDT_TriangleNormals, offsetList ) ) { // Just for debugging... we don't actually use any of this bool variable = _offsetIsVariable( MDT_TriangleNormals, offsetList ); uint32_t offset = _offsetGet( MDT_TriangleNormals, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { m_src->read( size ); } MM3DFILE_TriangleNormalsT fileTri; m_src->read( fileTri.flags ); m_src->read( fileTri.index ); m_src->read( fileTri.normal[0][0] ); m_src->read( fileTri.normal[0][1] ); m_src->read( fileTri.normal[0][2] ); m_src->read( fileTri.normal[1][0] ); m_src->read( fileTri.normal[1][1] ); m_src->read( fileTri.normal[1][2] ); m_src->read( fileTri.normal[2][0] ); m_src->read( fileTri.normal[2][1] ); m_src->read( fileTri.normal[2][2] ); log_debug( "triangle %d normals:\n", fileTri.index ); for ( unsigned v = 0; v < 3; v++ ) { log_debug( " v %d: %f %f %f\n", v, fileTri.normal[v][0], fileTri.normal[v][1], fileTri.normal[v][2] ); } } } #endif // 0 // Groups if ( _offsetIncluded( MDT_Groups, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Groups, offsetList ); uint32_t offset = _offsetGet( MDT_Groups, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned g = 0; g < count; g++ ) { if ( variable ) { m_src->read( size ); } Model::Group * grp = Model::Group::get(); uint16_t flags; uint32_t triCount; uint8_t smoothness; uint32_t materialIndex; char name[1024]; m_src->read( flags ); m_src->readAsciiz(name, sizeof(name) ); utf8chrtrunc( name, sizeof(name)-1 ); m_src->read( triCount ); for ( unsigned t = 0; t < triCount; t++ ) { uint32_t triIndex = 0; m_src->read( triIndex ); grp->m_triangleIndices.insert( triIndex ); } m_src->read( smoothness ); m_src->read( materialIndex ); grp->m_name = name; grp->m_smooth = smoothness; grp->m_selected = ((flags & MF_SELECTED) == MF_SELECTED); grp->m_visible = ((flags & MF_HIDDEN) != MF_HIDDEN); grp->m_materialIndex = materialIndex; modelGroups.push_back( grp ); } } // External Textures std::vector< std::string > texNames; if ( _offsetIncluded( MDT_ExtTextures, offsetList ) ) { bool variable = _offsetIsVariable( MDT_ExtTextures, offsetList ); uint32_t offset = _offsetGet( MDT_ExtTextures, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned t = 0; t < count; t++ ) { log_debug( "reading external texture %d/%d\n", t, count ); if ( variable ) { m_src->read( size ); } uint16_t flags; char filename[PATH_MAX]; m_src->read( flags ); m_src->readAsciiz(filename, sizeof(filename) ); utf8chrtrunc( filename, sizeof(filename)-1 ); replaceBackslash( filename ); log_debug( " filename is %s\n", filename ); std::string fullpath = getAbsolutePath( modelPath.c_str(), filename ); texNames.push_back( fullpath ); } } // Materials if ( _offsetIncluded( MDT_Materials, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Materials, offsetList ); uint32_t offset = _offsetGet( MDT_Materials, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned m = 0; m < count; m++ ) { log_debug( "reading material %d/%d\n", m, count ); if ( variable ) { m_src->read( size ); } uint16_t flags = 0; uint32_t texIndex = 0; char name[1024]; Model::Material * mat = Model::Material::get(); m_src->read( flags ); m_src->read( texIndex ); m_src->readAsciiz(name, sizeof(name) ); utf8chrtrunc( name, sizeof(name)-1 ); log_debug( " material name: %s\n", name ); mat->m_name = name; switch ( flags & 0x0f ) { case 0: log_debug( " got external texture %d\n", texIndex ); mat->m_type = Model::Material::MATTYPE_TEXTURE; if ( texIndex < texNames.size() ) { mat->m_filename = texNames[texIndex]; } else { mat->m_filename = ""; } break; case 13: mat->m_type = Model::Material::MATTYPE_COLOR; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; case 14: mat->m_type = Model::Material::MATTYPE_GRADIENT; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; case 15: mat->m_type = Model::Material::MATTYPE_BLANK; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; default: log_debug( " got unknown material type\n", texIndex ); mat->m_type = Model::Material::MATTYPE_BLANK; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; } mat->m_sClamp = ( (flags & MF_MAT_CLAMP_S) != 0 ); mat->m_tClamp = ( (flags & MF_MAT_CLAMP_T) != 0 ); unsigned i = 0; float32_t lightProp = 0; for ( i = 0; i < 4; i++ ) { m_src->read( lightProp ); mat->m_ambient[i] = lightProp; } for ( i = 0; i < 4; i++ ) { m_src->read( lightProp ); mat->m_diffuse[i] = lightProp; } for ( i = 0; i < 4; i++ ) { m_src->read( lightProp ); mat->m_specular[i] = lightProp; } for ( i = 0; i < 4; i++ ) { m_src->read( lightProp ); mat->m_emissive[i] = lightProp; } m_src->read( lightProp ); mat->m_shininess = lightProp; modelMaterials.push_back( mat ); } } // Texture coordinates if ( _offsetIncluded( MDT_TexCoords, offsetList ) ) { bool variable = _offsetIsVariable( MDT_TexCoords, offsetList ); uint32_t offset = _offsetGet( MDT_TexCoords, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned c = 0; c < count; c++ ) { if ( variable ) { m_src->read( size ); } MM3DFILE_TexCoordT tc; m_src->read( tc.flags ); m_src->read( tc.triangleIndex ); m_src->read( tc.sCoord[0] ); m_src->read( tc.sCoord[1] ); m_src->read( tc.sCoord[2] ); m_src->read( tc.tCoord[0] ); m_src->read( tc.tCoord[1] ); m_src->read( tc.tCoord[2] ); uint32_t triIndex = tc.triangleIndex; if ( triIndex < modelTriangles.size() ) { for ( unsigned v = 0; v < 3; v++ ) { modelTriangles[triIndex]->m_s[v] = tc.sCoord[v]; modelTriangles[triIndex]->m_t[v] = tc.tCoord[v]; } } } } // Canvas Background Images if ( _offsetIncluded( MDT_CanvasBackgrounds, offsetList ) ) { bool variable = _offsetIsVariable( MDT_CanvasBackgrounds, offsetList ); uint32_t offset = _offsetGet( MDT_CanvasBackgrounds, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned g = 0; g < count; g++ ) { log_debug( "reading canvas background %d/%d\n", g, count ); if ( variable ) { m_src->read( size ); } MM3DFILE_CanvasBackgroundT cb; m_src->read( cb.flags ); m_src->read( cb.viewIndex ); m_src->read( cb.scale ); m_src->read( cb.center[0] ); m_src->read( cb.center[1] ); m_src->read( cb.center[2] ); char name[PATH_MAX]; m_src->readAsciiz(name, sizeof(name) ); utf8chrtrunc( name, sizeof(name)-1 ); replaceBackslash( name ); std::string fileStr = getAbsolutePath( modelPath.c_str(), name ); model->setBackgroundImage( cb.viewIndex, fileStr.c_str() ); model->setBackgroundScale( cb.viewIndex, cb.scale ); model->setBackgroundCenter( cb.viewIndex, cb.center[0], cb.center[1], cb.center[2] ); } } // Joints if ( _offsetIncluded( MDT_Joints, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Joints, offsetList ); uint32_t offset = _offsetGet( MDT_Joints, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned j = 0; j < count; j++ ) { log_debug( "reading joint %d/%d\n", j, count ); if ( variable ) { m_src->read( size ); } MM3DFILE_JointT fileJoint; m_src->read( fileJoint.flags ); m_src->readBytes( (uint8_t *) fileJoint.name, sizeof(fileJoint.name) ); m_src->read( fileJoint.parentIndex ); m_src->read( fileJoint.localRot[0] ); m_src->read( fileJoint.localRot[1] ); m_src->read( fileJoint.localRot[2] ); m_src->read( fileJoint.localTrans[0] ); m_src->read( fileJoint.localTrans[1] ); m_src->read( fileJoint.localTrans[2] ); Model::Joint * joint = Model::Joint::get(); fileJoint.name[ sizeof(fileJoint.name) - 1 ] = '\0'; joint->m_name = fileJoint.name; joint->m_parent = fileJoint.parentIndex; for ( unsigned i = 0; i < 3; i++ ) { joint->m_localRotation[i] = fileJoint.localRot[i]; joint->m_localTranslation[i] = fileJoint.localTrans[i]; } uint16_t jointFlags = fileJoint.flags; joint->m_selected = ((jointFlags & MF_SELECTED) == MF_SELECTED); joint->m_visible = ((jointFlags & MF_HIDDEN) != MF_HIDDEN); modelJoints.push_back( joint ); } log_debug( "read %d joints\n", count ); } // Joint Vertices // Newer versions of the file format use MDT_WeightedInfluences instead. // We still want to read this data to use as a default in case the // weighted influences are not present. if ( _offsetIncluded( MDT_JointVertices, offsetList ) ) { bool variable = _offsetIsVariable( MDT_JointVertices, offsetList ); uint32_t offset = _offsetGet( MDT_JointVertices, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { m_src->read( size ); } uint32_t vertexIndex = 0; int32_t jointIndex = 0; m_src->read( vertexIndex ); m_src->read( jointIndex ); if ( vertexIndex < modelVertices.size() && (unsigned) jointIndex < modelJoints.size() ) { //modelVertices[ vertexIndex ]->m_boneId = jointIndex; model->addVertexInfluence( vertexIndex, jointIndex, Model::IT_Custom, 1.0 ); } else { missingElements = true; log_error( "vertex %d or joint %d out of range\n", vertexIndex, jointIndex ); } } log_debug( "read %d joints vertices\n", count ); } // Points if ( _offsetIncluded( MDT_Points, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Points, offsetList ); uint32_t offset = _offsetGet( MDT_Points, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned j = 0; j < count; j++ ) { log_debug( "reading Point %d/%d\n", j, count ); if ( variable ) { m_src->read( size ); } MM3DFILE_PointT filePoint; m_src->read( filePoint.flags ); m_src->readBytes( (uint8_t *) filePoint.name, sizeof(filePoint.name) ); m_src->read( filePoint.type ); m_src->read( filePoint.boneIndex ); m_src->read( filePoint.rot[0] ); m_src->read( filePoint.rot[1] ); m_src->read( filePoint.rot[2] ); m_src->read( filePoint.trans[0] ); m_src->read( filePoint.trans[1] ); m_src->read( filePoint.trans[2] ); filePoint.name[ sizeof(filePoint.name) - 1 ] = '\0'; float rot[3]; float trans[3]; for ( unsigned i = 0; i < 3; i++ ) { rot[i] = filePoint.rot[i]; trans[i] = filePoint.trans[i]; } int boneIndex = filePoint.boneIndex; int p = model->addPoint( filePoint.name, trans[0], trans[1], trans[2], rot[0], rot[1], rot[2], boneIndex ); int type = filePoint.type; model->setPointType( p, type ); uint16_t pointFlags = filePoint.flags; if ( (pointFlags & MF_SELECTED) == MF_SELECTED ) { model->selectPoint( p ); } if ( (pointFlags & MF_HIDDEN) == MF_HIDDEN) { model->hidePoint( p ); } } log_debug( "read %d points\n" ); } // Smooth Angles if ( _offsetIncluded( MDT_SmoothAngles, offsetList ) ) { bool variable = _offsetIsVariable( MDT_SmoothAngles, offsetList ); uint32_t offset = _offsetGet( MDT_SmoothAngles, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { m_src->read( size ); } MM3DFILE_SmoothAngleT fileSa; m_src->read( fileSa.groupIndex ); m_src->read( fileSa.angle ); if ( fileSa.angle > 180 ) { fileSa.angle = 180; } if ( fileSa.groupIndex < modelGroups.size() ) { model->setGroupAngle( fileSa.groupIndex, fileSa.angle ); } } log_debug( "read %d group smoothness angles\n", count ); } // Weighted influences if ( _offsetIncluded( MDT_WeightedInfluences, offsetList ) ) { bool variable = _offsetIsVariable( MDT_WeightedInfluences, offsetList ); uint32_t offset = _offsetGet( MDT_WeightedInfluences, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } unsigned vcount = model->getVertexCount(); for ( unsigned v = 0; v < vcount; v++ ) { model->removeAllVertexInfluences( v ); } unsigned pcount = model->getVertexCount(); for ( unsigned p = 0; p < pcount; p++ ) { model->removeAllPointInfluences( p ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { m_src->read( size ); } MM3DFILE_WeightedInfluenceT fileWi; m_src->read( fileWi.posType ); m_src->read( fileWi.posIndex ); m_src->read( fileWi.infIndex ); m_src->read( fileWi.infType ); m_src->read( fileWi.infWeight ); if ( fileWi.posType == Model::PT_Vertex || fileWi.posType == Model::PT_Point ) { Model::Position pos; pos.type = static_cast( fileWi.posType ); pos.index = fileWi.posIndex; Model::InfluenceTypeE type = Model::IT_Custom; switch ( fileWi.infType ) { case Model::IT_Custom: case Model::IT_Auto: case Model::IT_Remainder: type = static_cast( fileWi.infType ); break; default: log_error( "unknown influence type %d\n", fileWi.infType ); break; } double weight = ((double) fileWi.infWeight) / 100.0; log_debug( "adding position influence %d,%d,%f\n", pos.index, (int) type, (float) weight ); model->addPositionInfluence( pos, fileWi.infIndex, type, weight ); } } } // Texture Projections if ( _offsetIncluded( MDT_TexProjections, offsetList ) ) { bool variable = _offsetIsVariable( MDT_TexProjections, offsetList ); uint32_t offset = _offsetGet( MDT_TexProjections, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned j = 0; j < count; j++ ) { log_debug( "reading Projection %d/%d\n", j, count ); if ( variable ) { m_src->read( size ); } uint16_t flags = 0; m_src->read( flags ); char nameBytes[40]; m_src->readBytes( (uint8_t *) nameBytes, sizeof(nameBytes) ); std::string name; name.assign( (char *) nameBytes, 40 ); int32_t type = 0; m_src->read( type ); double vec[3]; float fvec[3]; unsigned i = 0; // position for ( unsigned i = 0; i < 3; i++ ) { m_src->read( fvec[i] ); vec[i] = fvec[i]; } int proj = model->addProjection( name.c_str(), type, vec[0], vec[1], vec[2] ); // up vector for ( unsigned i = 0; i < 3; i++ ) { m_src->read( fvec[i] ); vec[i] = fvec[i]; } model->setProjectionUp( proj, vec ); // seam vector for ( unsigned i = 0; i < 3; i++ ) { m_src->read( fvec[i] ); vec[i] = fvec[i]; } model->setProjectionSeam( proj, vec ); double uv[2][2]; float fuv[2][2]; // texture coordinate range for ( i = 0; i < 2; i++ ) { for ( int j = 0; j < 2; j++ ) { m_src->read( fuv[i][j] ); uv[i][j] = fuv[i][j]; } } model->setProjectionRange( proj, uv[0][0], uv[0][1], uv[1][0], uv[1][1] ); } log_debug( "read %d projections\n" ); } // Texture Projection Triangles (have to read this after projections) if ( _offsetIncluded( MDT_ProjectionTriangles, offsetList ) ) { bool variable = _offsetIsVariable( MDT_ProjectionTriangles, offsetList ); uint32_t offset = _offsetGet( MDT_ProjectionTriangles, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned c = 0; c < count; c++ ) { if ( variable ) { m_src->read( size ); } uint32_t proj = 0; uint32_t triCount = 0; uint32_t tri = 0; m_src->read( proj ); m_src->read( triCount ); uint32_t t; for ( t = 0; t < triCount; t++ ) { m_src->read( tri ); model->setTriangleProjection( tri, proj ); } } } // Skeletal Animations if ( _offsetIncluded( MDT_SkelAnims, offsetList ) ) { bool variable = _offsetIsVariable( MDT_SkelAnims, offsetList ); uint32_t offset = _offsetGet( MDT_SkelAnims, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned s = 0; s < count; s++ ) { log_debug( "reading skel anim %d/%d\n", s, count ); if ( variable ) { m_src->read( size ); } uint16_t flags; char name[1024]; float32_t fps; uint32_t frameCount; m_src->read( flags ); m_src->readAsciiz(name, sizeof(name) ); utf8chrtrunc( name, sizeof(name)-1 ); log_debug( " name is %s\n", name ); m_src->read( fps ); m_src->read( frameCount ); unsigned anim = model->addAnimation( Model::ANIMMODE_SKELETAL, name ); model->setAnimFPS( Model::ANIMMODE_SKELETAL, anim, fps ); model->setAnimFrameCount( Model::ANIMMODE_SKELETAL, anim, frameCount ); for ( unsigned f = 0; f < frameCount; f++ ) { uint32_t keyframeCount; m_src->read( keyframeCount ); for ( unsigned k = 0; k < keyframeCount; k++ ) { MM3DFILE_SkelKeyframeT fileKf; m_src->read( fileKf.jointIndex ); m_src->read( fileKf.keyframeType ); m_src->read( fileKf.param[0] ); m_src->read( fileKf.param[1] ); m_src->read( fileKf.param[2] ); model->setSkelAnimKeyframe( anim, f, fileKf.jointIndex, (fileKf.keyframeType ? false : true), fileKf.param[0], fileKf.param[1], fileKf.param[2] ); } } } } // Frame Animations if ( _offsetIncluded( MDT_FrameAnims, offsetList ) ) { bool variable = _offsetIsVariable( MDT_FrameAnims, offsetList ); uint32_t offset = _offsetGet( MDT_FrameAnims, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned a = 0; a < count; a++ ) { log_debug( "reading frame animation %d/%d\n", a, count ); if ( variable ) { m_src->read( size ); } if ( size > m_src->getRemaining() ) { log_error( "Size of frame animation is too large for file data (%d > %d)\n", size, m_src->getRemaining() ); return Model::ERROR_BAD_DATA; } uint16_t flags; char name[1024]; float32_t fps; uint32_t frameCount; m_src->read( flags ); m_src->readAsciiz(name, sizeof(name) ); utf8chrtrunc( name, sizeof(name)-1 ); log_debug( "anim name '%s' size %d\n", name, size ); m_src->read( fps ); log_debug( "fps %f\n", fps ); m_src->read( frameCount ); log_debug( "frame count %u\n", frameCount ); if ( (frameCount > size) || ((frameCount * modelVertices.size() * sizeof(float32_t)) * 3 > (size - 10))) { log_error( "Frame count for animation is too large for file data\n" ); return Model::ERROR_BAD_DATA; } unsigned anim = model->addAnimation( Model::ANIMMODE_FRAME, name ); model->setAnimFPS( Model::ANIMMODE_FRAME, anim, fps ); model->setAnimFrameCount( Model::ANIMMODE_FRAME, anim, frameCount ); for ( unsigned f = 0; f < frameCount; f++ ) { unsigned maxVertex = 0; float32_t coord[3]; for ( unsigned v = 0; v < modelVertices.size(); v++ ) { for ( unsigned i = 0; i < 3; i++ ) { m_src->read( coord[i] ); } model->setFrameAnimVertexCoords( anim, f, v, coord[0], coord[1], coord[2] ); maxVertex = v; } maxVertex = maxVertex + 1; if ( (maxVertex) != modelVertices.size() ) { missingElements = true; log_error( "Vertex count for frame animation %d, frame %d has %d vertices, should be %d\n", anim, f, maxVertex, modelVertices.size() ); } } } } // Frame Animation Points if ( _offsetIncluded( MDT_FrameAnimPoints, offsetList ) ) { bool variable = _offsetIsVariable( MDT_FrameAnimPoints, offsetList ); uint32_t offset = _offsetGet( MDT_FrameAnimPoints, offsetList ); m_src->seek(offset); uint16_t flags = 0; uint32_t count = 0; m_src->read( flags ); m_src->read( count ); uint32_t size = 0; if ( !variable ) { m_src->read( size ); } for ( unsigned a = 0; a < count; a++ ) { if ( variable ) { m_src->read( size ); } uint16_t flags; uint32_t anim; uint32_t frameCount; m_src->read( flags ); m_src->read( anim ); m_src->read( frameCount ); size_t pcount = model->getPointCount(); for ( unsigned f = 0; f < frameCount; f++ ) { float32_t rot[3]; float32_t trans[3]; for ( unsigned p = 0; p < pcount; p++ ) { for ( unsigned i = 0; i < 3; i++ ) { m_src->read( rot[i] ); } for ( unsigned i = 0; i < 3; i++ ) { m_src->read( trans[i] ); } model->setFrameAnimPointCoords( anim, f, p, trans[0], trans[1], trans[2] ); model->setFrameAnimPointRotation( anim, f, p, rot[0], rot[1], rot[2] ); } } } } // Read unknown data UnknownDataList::iterator it; for ( it = unknownList.begin(); it != unknownList.end(); it++ ) { Model::FormatData * fd = new Model::FormatData; fd->offsetType = (*it).offsetType; m_src->seek((*it).offsetValue); log_debug( "unknown data is type %x...\n", fd->offsetType ); fd->data = new uint8_t[ (*it).dataLen ]; fd->len = (*it).dataLen; m_src->readBytes( fd->data, (*it).dataLen ); if ( model->addFormatData( fd ) < 0 ) { delete fd; } } // Account for missing elements (vertices, triangles, textures, joints) { unsigned vcount = modelVertices.size(); unsigned tcount = modelTriangles.size(); unsigned gcount = modelGroups.size(); unsigned jcount = modelJoints.size(); unsigned mcount = modelMaterials.size(); // for ( unsigned v = 0; v < vcount; v++ ) // { // if ( modelVertices[v]->m_boneId >= (signed) jcount ) // { // missingElements = true; // log_error( "Vertex %d uses missing bone joint %d\n", v, modelVertices[v]->m_boneId ); // } // } for ( unsigned t = 0; t < tcount; t++ ) { for ( unsigned i = 0; i < 3; i++ ) { if ( modelTriangles[t]->m_vertexIndices[i] >= vcount ) { missingElements = true; log_error( "Triangle %d uses missing vertex %d\n", t, modelTriangles[t]->m_vertexIndices[i] ); } } } for ( unsigned g = 0; g < gcount; g++ ) { for ( std::set::const_iterator it = modelGroups[g]->m_triangleIndices.begin(); it != modelGroups[g]->m_triangleIndices.end(); ++it ) { if ( *it >= (signed) tcount ) { missingElements = true; log_error( "Group %d uses missing triangle %d\n", g, *it ); } } if ( modelGroups[g]->m_materialIndex >= (signed) mcount ) { missingElements = true; log_error( "Group %d uses missing texture %d\n", g, modelGroups[g]->m_materialIndex ); } } for ( unsigned j = 0; j < jcount; j++ ) { if ( modelJoints[j]->m_parent >= (signed) jcount ) { log_warning( "Joint %d has bad parent joint, checking endianness\n", j ); if ( htonl( modelJoints[j]->m_parent ) < jcount ) { modelJoints[j]->m_parent = htonl( modelJoints[j]->m_parent ); } else if ( htol_u32( modelJoints[j]->m_parent ) < jcount ) { modelJoints[j]->m_parent = htol_u32( modelJoints[j]->m_parent ); } else { missingElements = true; log_error( "Joint %d has missing parent joint %d\n", j, modelJoints[j]->m_parent ); } } } } if ( missingElements ) { log_warning( "missing elements in file\n" ); return Model::ERROR_BAD_DATA; } else { model->setupJoints(); return Model::ERROR_NONE; } } Model::ModelErrorE MisfitFilter::writeFile( Model * model, const char * const filename, ModelFilter::Options * o ) { if ( filename == NULL || filename[0] == '\0' ) { return Model::ERROR_BAD_ARGUMENT; } if ( sizeof( float32_t ) != 4 ) { msg_error( transll( QT_TRANSLATE_NOOP( "LowLevel", "MM3D encountered an unexpected data size problem\nSee Help->About to contact the developers" )).c_str() ); return Model::ERROR_FILE_OPEN; } Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); bool doWrite[ MDT_MAX ]; unsigned t = 0; for ( t = 0; t < MDT_MAX; t++ ) { doWrite[t] = false; } // Get model data vector & modelVertices = getVertexList( model ); vector & modelTriangles = getTriangleList( model ); vector & modelGroups = getGroupList( model ); vector & modelMaterials = getMaterialList( model ); vector & modelJoints = getJointList( model ); vector & modelPoints = getPointList( model ); //vector & modelProjections = getProjectionList( model ); vector & modelSkels = getSkelList( model ); vector & modelFrames = getFrameList( model ); int backgrounds = 0; for ( t = 0; t < 6; t++ ) { const char * file = model->getBackgroundImage( t ); if ( file[0] != '\0' ) { backgrounds++; } } bool haveProjectionTriangles = false; if ( model->getProjectionCount() > 0 ) { size_t tcount = model->getTriangleCount(); for ( size_t t = 0; !haveProjectionTriangles && t < tcount; t++ ) { if ( model->getTriangleProjection( t ) >= 0 ) { haveProjectionTriangles = true; } } } // Find out what sections we need to write doWrite[ MDT_Meta ] = (model->getMetaDataCount() > 0); doWrite[ MDT_Vertices ] = (modelVertices.size() > 0); doWrite[ MDT_Triangles ] = (modelTriangles.size() > 0); doWrite[ MDT_TriangleNormals ] = (modelTriangles.size() > 0); doWrite[ MDT_Groups ] = (modelGroups.size() > 0); doWrite[ MDT_Materials ] = (modelMaterials.size() > 0); doWrite[ MDT_ExtTextures ] = doWrite[ MDT_Materials ]; doWrite[ MDT_TexCoords ] = true; // Some users map texture coordinates before assigning a texture (think: paint texture) doWrite[ MDT_ProjectionTriangles ] = haveProjectionTriangles; doWrite[ MDT_CanvasBackgrounds ] = (backgrounds > 0); doWrite[ MDT_Joints ] = (modelJoints.size() > 0); doWrite[ MDT_JointVertices ] = doWrite[ MDT_Joints ]; doWrite[ MDT_Points ] = (model->getPointCount() > 0); doWrite[ MDT_SmoothAngles ] = (modelGroups.size() > 0); doWrite[ MDT_WeightedInfluences ] = (modelJoints.size() > 0); doWrite[ MDT_TexProjections ] = (model->getProjectionCount() > 0); doWrite[ MDT_SkelAnims ] = (model->getAnimCount( Model::ANIMMODE_SKELETAL ) > 0); doWrite[ MDT_FrameAnims ] = (model->getAnimCount( Model::ANIMMODE_FRAME ) > 0); doWrite[ MDT_FrameAnimPoints ] = (model->getAnimCount( Model::ANIMMODE_FRAME ) > 0 && model->getPointCount() > 0 ); doWrite[ MDT_RelativeAnims ] = (model->getAnimCount( Model::ANIMMODE_FRAMERELATIVE ) > 0); uint8_t modelFlags = 0x00; // Write header MisfitOffsetList offsetList; _addOffset( MDT_Meta, doWrite[ MDT_Meta ], offsetList ); _addOffset( MDT_Vertices, doWrite[ MDT_Vertices ], offsetList ); _addOffset( MDT_Triangles, doWrite[ MDT_Triangles ], offsetList ); _addOffset( MDT_TriangleNormals, doWrite[ MDT_TriangleNormals ], offsetList ); _addOffset( MDT_Groups, doWrite[ MDT_Groups ], offsetList ); _addOffset( MDT_Materials, doWrite[ MDT_Materials ], offsetList ); _addOffset( MDT_ExtTextures, doWrite[ MDT_ExtTextures ], offsetList ); _addOffset( MDT_TexCoords, doWrite[ MDT_TexCoords ], offsetList ); _addOffset( MDT_ProjectionTriangles, doWrite[ MDT_ProjectionTriangles ], offsetList ); _addOffset( MDT_CanvasBackgrounds, doWrite[ MDT_CanvasBackgrounds ], offsetList ); _addOffset( MDT_Joints, doWrite[ MDT_Joints ], offsetList ); _addOffset( MDT_JointVertices, doWrite[ MDT_JointVertices ], offsetList ); _addOffset( MDT_Points, doWrite[ MDT_Points ], offsetList ); _addOffset( MDT_SmoothAngles, doWrite[ MDT_SmoothAngles ], offsetList ); _addOffset( MDT_WeightedInfluences, doWrite[ MDT_WeightedInfluences ], offsetList ); _addOffset( MDT_TexProjections, doWrite[ MDT_TexProjections ], offsetList ); _addOffset( MDT_SkelAnims, doWrite[ MDT_SkelAnims ], offsetList ); _addOffset( MDT_FrameAnims, doWrite[ MDT_FrameAnims ], offsetList ); _addOffset( MDT_FrameAnimPoints, doWrite[ MDT_FrameAnimPoints ], offsetList ); unsigned formatDataCount = model->getFormatDataCount(); unsigned f = 0; for ( f = 0; f < formatDataCount; f++ ) { Model::FormatData * fd = model->getFormatData( f ); if ( fd->offsetType != 0 ) { MisfitOffsetT mo; mo.offsetType = (fd->offsetType | OFFSET_DIRTY_MASK); mo.offsetValue = 0; offsetList.push_back( mo ); log_warning( "adding unknown data type %04x\n", mo.offsetType ); } } _addOffset( MDT_EndOfFile, true, offsetList ); uint8_t offsetCount = (uint8_t) offsetList.size(); m_dst->writeBytes( (const uint8_t *) MAGIC, strlen(MAGIC) ); m_dst->write( WRITE_VERSION_MAJOR ); m_dst->write( WRITE_VERSION_MINOR ); m_dst->write( modelFlags ); m_dst->write( offsetCount ); for ( t = 0; t < offsetCount; t++ ) { MisfitOffsetT & mo = offsetList[t]; m_dst->write( mo.offsetType ); m_dst->write( mo.offsetValue ); } log_debug( "wrote %d offsets\n", offsetCount ); // Write data // Meta data if ( doWrite[ MDT_Meta ] ) { _setOffset( MDT_Meta, m_dst->offset(), offsetList ); _setUniformOffset( MDT_Meta, false, offsetList ); unsigned count = model->getMetaDataCount(); writeHeaderA( 0x0000, count ); for ( unsigned m = 0; m < count; m++ ) { char key[1024]; char value[1024]; model->getMetaData( m, key, sizeof(key), value, sizeof(value) ); unsigned keyLen = strlen( key ) + 1; unsigned valueLen = strlen( value ) + 1; m_dst->write(keyLen + valueLen); m_dst->writeBytes( (const uint8_t *) key, keyLen ); m_dst->writeBytes( (const uint8_t *) value, valueLen ); } log_debug( "wrote %d meta data pairs\n", count ); } // Vertices if ( doWrite[ MDT_Vertices ] ) { _setOffset( MDT_Vertices, m_dst->offset(), offsetList ); _setUniformOffset( MDT_Vertices, true, offsetList ); unsigned count = modelVertices.size(); writeHeaderB( 0x0000, count, FILE_VERTEX_SIZE ); for ( unsigned v = 0; v < count; v++ ) { MM3DFILE_VertexT fileVertex; fileVertex.flags = 0x0000; fileVertex.flags |= (modelVertices[v]->m_visible) ? 0 : MF_HIDDEN; fileVertex.flags |= (modelVertices[v]->m_selected) ? MF_SELECTED : 0; fileVertex.flags |= (modelVertices[v]->m_free) ? MF_VERTFREE : 0; fileVertex.coord[0] = modelVertices[v]->m_coord[0]; fileVertex.coord[1] = modelVertices[v]->m_coord[1]; fileVertex.coord[2] = modelVertices[v]->m_coord[2]; m_dst->write( fileVertex.flags ); m_dst->write( fileVertex.coord[0] ); m_dst->write( fileVertex.coord[1] ); m_dst->write( fileVertex.coord[2] ); } log_debug( "wrote %d vertices\n", count ); } // Triangles if ( doWrite[ MDT_Triangles ] ) { _setOffset( MDT_Triangles, m_dst->offset(), offsetList ); _setUniformOffset( MDT_Triangles, true, offsetList ); unsigned count = modelTriangles.size(); writeHeaderB( 0x0000, count, FILE_TRIANGLE_SIZE ); for ( unsigned t = 0; t < count; t++ ) { MM3DFILE_TriangleT fileTriangle; fileTriangle.flags = 0x0000; fileTriangle.flags |= (modelTriangles[t]->m_visible) ? 0 : MF_HIDDEN; fileTriangle.flags |= (modelTriangles[t]->m_selected) ? MF_SELECTED : 0; fileTriangle.flags = fileTriangle.flags; fileTriangle.vertex[0] = modelTriangles[t]->m_vertexIndices[0]; fileTriangle.vertex[1] = modelTriangles[t]->m_vertexIndices[1]; fileTriangle.vertex[2] = modelTriangles[t]->m_vertexIndices[2]; m_dst->write( fileTriangle.flags ); m_dst->write( fileTriangle.vertex[0] ); m_dst->write( fileTriangle.vertex[1] ); m_dst->write( fileTriangle.vertex[2] ); } log_debug( "wrote %d triangles\n", count ); } // Triangle Normals if ( doWrite[ MDT_TriangleNormals ] ) { _setOffset( MDT_TriangleNormals, m_dst->offset(), offsetList ); _setUniformOffset( MDT_TriangleNormals, true, offsetList ); unsigned count = modelTriangles.size(); writeHeaderB( 0x0000, count, FILE_TRIANGLE_NORMAL_SIZE ); for ( unsigned t = 0; t < count; t++ ) { MM3DFILE_TriangleNormalsT fileNormals; fileNormals.flags = 0x0000; fileNormals.index = t; for ( unsigned v = 0; v < 3; v++ ) { fileNormals.normal[v][0] = modelTriangles[t]->m_vertexNormals[v][0]; fileNormals.normal[v][1] = modelTriangles[t]->m_vertexNormals[v][1]; fileNormals.normal[v][2] = modelTriangles[t]->m_vertexNormals[v][2]; } m_dst->write( fileNormals.flags ); m_dst->write( fileNormals.index ); m_dst->write( fileNormals.normal[0][0] ); m_dst->write( fileNormals.normal[0][1] ); m_dst->write( fileNormals.normal[0][2] ); m_dst->write( fileNormals.normal[1][0] ); m_dst->write( fileNormals.normal[1][1] ); m_dst->write( fileNormals.normal[1][2] ); m_dst->write( fileNormals.normal[2][0] ); m_dst->write( fileNormals.normal[2][1] ); m_dst->write( fileNormals.normal[2][2] ); } log_debug( "wrote %d triangle normals\n", count ); } // Groups if ( doWrite[ MDT_Groups ] ) { _setOffset( MDT_Groups, m_dst->offset(), offsetList ); _setUniformOffset( MDT_Groups, false, offsetList ); unsigned count = modelGroups.size(); writeHeaderA( 0x0000, count ); unsigned baseSize = sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t); for ( unsigned g = 0; g < count; g++ ) { Model::Group * grp = modelGroups[g]; unsigned groupSize = baseSize + grp->m_name.length() + 1 + (grp->m_triangleIndices.size() * sizeof(uint32_t)); uint16_t flags = 0x0000; flags |= (modelGroups[g]->m_visible) ? 0 : MF_HIDDEN; flags |= (modelGroups[g]->m_selected) ? MF_SELECTED : 0; uint32_t triCount = grp->m_triangleIndices.size(); m_dst->write( groupSize ); m_dst->write( flags ); m_dst->writeBytes( (const uint8_t *) grp->m_name.c_str(), grp->m_name.length() + 1 ); m_dst->write( triCount ); for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { uint32_t triIndex = *it; m_dst->write( triIndex ); } uint8_t smoothness = grp->m_smooth; uint32_t materialIndex = grp->m_materialIndex; m_dst->write( smoothness ); m_dst->write( materialIndex ); } log_debug( "wrote %d groups\n", count ); } int texNum = 0; // Materials if ( doWrite[ MDT_Materials ] ) { _setOffset( MDT_Materials, m_dst->offset(), offsetList ); _setUniformOffset( MDT_Materials, false, offsetList ); unsigned count = modelMaterials.size(); writeHeaderA( 0x0000, count ); unsigned baseSize = sizeof(uint16_t) + sizeof(uint32_t) + (sizeof(float32_t) * 17); for ( unsigned m = 0; m < count; m++ ) { Model::Material * mat = modelMaterials[m]; unsigned matSize = baseSize + mat->m_name.length() + 1; uint16_t flags = 0x0000; uint32_t texIndex = texNum; // TODO deal with embedded textures switch ( mat->m_type ) { case Model::Material::MATTYPE_COLOR: flags = 0x000d; break; case Model::Material::MATTYPE_GRADIENT: flags = 0x000e; break; case Model::Material::MATTYPE_BLANK: flags = 0x000f; break; case Model::Material::MATTYPE_TEXTURE: flags = 0x0000; texNum++; break; default: break; } if ( mat->m_sClamp ) { flags |= MF_MAT_CLAMP_S; } if ( mat->m_tClamp ) { flags |= MF_MAT_CLAMP_T; } m_dst->write( matSize ); m_dst->write( flags ); m_dst->write( texIndex ); m_dst->writeBytes( (const uint8_t *) mat->m_name.c_str(), mat->m_name.length() + 1 ); unsigned i = 0; float32_t lightProp = 0; for ( i = 0; i < 4; i++ ) { lightProp = mat->m_ambient[i]; m_dst->write( lightProp ); } for ( i = 0; i < 4; i++ ) { lightProp = mat->m_diffuse[i]; m_dst->write( lightProp ); } for ( i = 0; i < 4; i++ ) { lightProp = mat->m_specular[i]; m_dst->write( lightProp ); } for ( i = 0; i < 4; i++ ) { lightProp = mat->m_emissive[i]; m_dst->write( lightProp ); } lightProp = mat->m_shininess; m_dst->write( lightProp ); } log_debug( "wrote %d materials with %d internal textures\n", count, texNum ); } // External Textures if ( doWrite[ MDT_ExtTextures ] ) { _setOffset( MDT_ExtTextures, m_dst->offset(), offsetList ); _setUniformOffset( MDT_ExtTextures, false, offsetList ); unsigned count = modelMaterials.size(); writeHeaderA( 0x0000, count ); unsigned baseSize = sizeof(uint16_t); for ( unsigned m = 0; m < count; m++ ) { Model::Material * mat = modelMaterials[m]; if ( mat->m_type == Model::Material::MATTYPE_TEXTURE ) { std::string fileStr = getRelativePath( modelPath.c_str(), mat->m_filename.c_str() ); char filename[PATH_MAX]; strncpy( filename, fileStr.c_str(), PATH_MAX ); utf8chrtrunc( filename, sizeof(filename)-1 ); replaceSlash( filename ); unsigned texSize = baseSize + strlen(filename) + 1; uint16_t flags = 0x0000; m_dst->write( texSize ); m_dst->write( flags ); m_dst->writeBytes( (const uint8_t *) filename, strlen(filename) + 1 ); log_debug( "material file is %s\n", filename ); } } log_debug( "wrote %d external textures\n", texNum ); } // Texture Coordinates if ( doWrite[ MDT_TexCoords ] ) { _setOffset( MDT_TexCoords, m_dst->offset(), offsetList ); _setUniformOffset( MDT_TexCoords, true, offsetList ); unsigned count = modelTriangles.size(); writeHeaderB( 0x0000, count, FILE_TEXCOORD_SIZE ); for ( unsigned t = 0; t < count; t++ ) { Model::Triangle * tri = modelTriangles[t]; MM3DFILE_TexCoordT tc; tc.flags = 0x0000; tc.triangleIndex = t; for ( unsigned v = 0; v < 3; v++ ) { tc.sCoord[v] = tri->m_s[v]; tc.tCoord[v] = tri->m_t[v]; } m_dst->write( tc.flags ); m_dst->write( tc.triangleIndex ); m_dst->write( tc.sCoord[0] ); m_dst->write( tc.sCoord[1] ); m_dst->write( tc.sCoord[2] ); m_dst->write( tc.tCoord[0] ); m_dst->write( tc.tCoord[1] ); m_dst->write( tc.tCoord[2] ); } log_debug( "wrote %d texture coordinates\n", count ); } // Texture Projection Triangles if ( doWrite[ MDT_ProjectionTriangles ] ) { _setOffset( MDT_ProjectionTriangles, m_dst->offset(), offsetList ); _setUniformOffset( MDT_ProjectionTriangles, false, offsetList ); unsigned pcount = model->getProjectionCount(); writeHeaderA( 0x0000, pcount ); for ( unsigned p = 0; p < pcount; p++ ) { unsigned wcount = 0; // triangles to write unsigned tcount = model->getTriangleCount(); unsigned t; for ( t = 0; t < tcount; t++ ) { if ( model->getTriangleProjection(t) == (int) p ) { wcount++; } } uint32_t triSize = sizeof(uint32_t) * 2 + sizeof(uint32_t) * wcount; uint32_t writeProj = (uint32_t) p; uint32_t writeCount = (uint32_t) wcount; m_dst->write( triSize ); m_dst->write( writeProj ); m_dst->write( writeCount ); for ( t = 0; t < tcount; t++ ) { if ( model->getTriangleProjection(t) == (int) p ) { uint32_t tri = t; m_dst->write( tri ); } } } log_debug( "wrote %d external textures\n", texNum ); } // Canvas Backgrounds if ( doWrite[ MDT_CanvasBackgrounds ] ) { _setOffset( MDT_CanvasBackgrounds, m_dst->offset(), offsetList ); _setUniformOffset( MDT_CanvasBackgrounds, false, offsetList ); unsigned count = backgrounds; writeHeaderA( 0x0000, count ); unsigned baseSize = FILE_CANVAS_BACKGROUND_SIZE; for ( unsigned b = 0; b < 6; b++ ) { const char * file = model->getBackgroundImage( b ); if ( file[0] != '\0' ) { MM3DFILE_CanvasBackgroundT cb; cb.flags = 0x0000; cb.viewIndex = b; cb.scale = model->getBackgroundScale( b ); model->getBackgroundCenter( b, cb.center[0], cb.center[1], cb.center[2] ); cb.center[0] = cb.center[0]; cb.center[1] = cb.center[1]; cb.center[2] = cb.center[2]; std::string fileStr = getRelativePath( modelPath.c_str(), file ); unsigned backSize = baseSize + fileStr.size() + 1; char * filedup = strdup( fileStr.c_str() ); replaceSlash( filedup ); utf8chrtrunc( filedup, PATH_MAX-1 ); m_dst->write( backSize ); m_dst->write( cb.flags ); m_dst->write( cb.viewIndex ); m_dst->write( cb.scale ); m_dst->write( cb.center[0] ); m_dst->write( cb.center[1] ); m_dst->write( cb.center[2] ); m_dst->writeBytes( (const uint8_t *) filedup, fileStr.size() + 1 ); free( filedup ); } } log_debug( "wrote %d canvas backgrounds\n", count ); } // Joints if ( doWrite[ MDT_Joints ] ) { _setOffset( MDT_Joints, m_dst->offset(), offsetList ); _setUniformOffset( MDT_Joints, true, offsetList ); unsigned count = modelJoints.size(); writeHeaderB( 0x0000, count, FILE_JOINT_SIZE ); for ( unsigned j = 0; j < count; j++ ) { MM3DFILE_JointT fileJoint; Model::Joint * joint = modelJoints[j]; fileJoint.flags = 0x0000; fileJoint.flags |= (modelJoints[j]->m_visible) ? 0 : MF_HIDDEN; fileJoint.flags |= (modelJoints[j]->m_selected) ? MF_SELECTED : 0; strncpy( fileJoint.name, joint->m_name.c_str(), sizeof(fileJoint.name) ); utf8chrtrunc( fileJoint.name, sizeof(fileJoint.name)-1 ); fileJoint.parentIndex = joint->m_parent; for ( unsigned i = 0; i < 3; i++ ) { fileJoint.localRot[i] = joint->m_localRotation[i]; fileJoint.localTrans[i] = joint->m_localTranslation[i]; } m_dst->write( fileJoint.flags ); m_dst->writeBytes( (const uint8_t *) fileJoint.name, sizeof(fileJoint.name) ); m_dst->write( fileJoint.parentIndex ); m_dst->write( fileJoint.localRot[0] ); m_dst->write( fileJoint.localRot[1] ); m_dst->write( fileJoint.localRot[2] ); m_dst->write( fileJoint.localTrans[0] ); m_dst->write( fileJoint.localTrans[1] ); m_dst->write( fileJoint.localTrans[2] ); } log_debug( "wrote %d joints\n", count ); } // Joint Vertices // Newer versions of the file format do not use this section, but old // versions of mm3d need it. Write it for the sake of backwards // compatibility if ( doWrite[ MDT_JointVertices ] ) { _setOffset( MDT_JointVertices, m_dst->offset(), offsetList ); _setUniformOffset( MDT_JointVertices, true, offsetList ); unsigned count = 0; unsigned vcount = modelVertices.size(); unsigned v = 0; for ( v = 0; v < vcount; v++ ) { if ( model->getPrimaryVertexInfluence( v ) >= 0 ) { count++; } } writeHeaderB( 0x0000, count, FILE_JOINT_VERTEX_SIZE ); for ( v = 0; v < vcount; v++ ) { int boneId = model->getPrimaryVertexInfluence( v ); if ( boneId >= 0 ) { MM3DFILE_JointVertexT fileJv; fileJv.vertexIndex = v; fileJv.jointIndex = boneId; m_dst->write( fileJv.vertexIndex ); m_dst->write( fileJv.jointIndex ); } } log_debug( "wrote %d joint vertex assignments\n", count ); } // Points if ( doWrite[ MDT_Points ] ) { _setOffset( MDT_Points, m_dst->offset(), offsetList ); _setUniformOffset( MDT_Points, true, offsetList ); unsigned count = model->getPointCount(); writeHeaderB( 0x0000, count, FILE_POINT_SIZE ); for ( unsigned p = 0; p < count; p++ ) { MM3DFILE_PointT filePoint; filePoint.flags = 0x0000; filePoint.flags |= (model->isPointVisible(p)) ? 0 : MF_HIDDEN; filePoint.flags |= (model->isPointSelected(p)) ? MF_SELECTED : 0; strncpy( filePoint.name, model->getPointName(p), sizeof(filePoint.name) ); utf8chrtrunc( filePoint.name, sizeof(filePoint.name)-1 ); filePoint.boneIndex = model->getPrimaryPointInfluence( p ); Model::Point * point = modelPoints[p]; for ( unsigned i = 0; i < 3; i++ ) { filePoint.rot[i] = point->m_rot[i]; filePoint.trans[i] = point->m_trans[i]; } m_dst->write( filePoint.flags ); m_dst->writeBytes( (const uint8_t *) filePoint.name, sizeof(filePoint.name) ); m_dst->write( filePoint.type ); m_dst->write( filePoint.boneIndex ); m_dst->write( filePoint.rot[0] ); m_dst->write( filePoint.rot[1] ); m_dst->write( filePoint.rot[2] ); m_dst->write( filePoint.trans[0] ); m_dst->write( filePoint.trans[1] ); m_dst->write( filePoint.trans[2] ); } log_debug( "wrote %d points\n", count ); } // Smooth Angles if ( doWrite[ MDT_SmoothAngles ] ) { _setOffset( MDT_SmoothAngles, m_dst->offset(), offsetList ); _setUniformOffset( MDT_SmoothAngles, true, offsetList ); unsigned count = modelGroups.size(); writeHeaderB( 0x0000, count, FILE_SMOOTH_ANGLE_SIZE ); for ( unsigned t = 0; t < count; t++ ) { MM3DFILE_SmoothAngleT fileSa; fileSa.groupIndex = t; fileSa.angle = model->getGroupAngle( t ); m_dst->write( fileSa.groupIndex ); m_dst->write( fileSa.angle ); } log_debug( "wrote %d group smoothness angles\n", count ); } // Weighted influences if ( doWrite[ MDT_WeightedInfluences ] ) { _setOffset( MDT_WeightedInfluences, m_dst->offset(), offsetList ); _setUniformOffset( MDT_WeightedInfluences, true, offsetList ); Model::InfluenceList ilist; Model::InfluenceList::iterator it; unsigned count = 0; unsigned vcount = modelVertices.size(); unsigned pcount = modelPoints.size(); unsigned v = 0; unsigned p = 0; for ( v = 0; v < vcount; v++ ) { model->getVertexInfluences( v, ilist ); count += ilist.size(); } for ( p = 0; p < pcount; p++ ) { model->getPointInfluences( p, ilist ); count += ilist.size(); } writeHeaderB( 0x0000, count, FILE_WEIGHTED_INFLUENCE_SIZE ); for ( v = 0; v < vcount; v++ ) { model->getVertexInfluences( v, ilist ); for ( it = ilist.begin(); it != ilist.end(); it++ ) { MM3DFILE_WeightedInfluenceT fileWi; fileWi.posType = Model::PT_Vertex; fileWi.posIndex = v; fileWi.infType = (*it).m_type; fileWi.infIndex = (*it).m_boneId; fileWi.infWeight = (int) ((*it).m_weight * 100.1); // round up slightly to prevent loss m_dst->write( fileWi.posType ); m_dst->write( fileWi.posIndex ); m_dst->write( fileWi.infIndex ); m_dst->write( fileWi.infType ); m_dst->write( fileWi.infWeight ); } } for ( p = 0; p < pcount; p++ ) { model->getPointInfluences( p, ilist ); for ( it = ilist.begin(); it != ilist.end(); it++ ) { MM3DFILE_WeightedInfluenceT fileWi; fileWi.posType = Model::PT_Point; fileWi.posIndex = p; fileWi.infType = (*it).m_type; fileWi.infIndex = (*it).m_boneId; fileWi.infWeight = (int) ((*it).m_weight * 100.1); // round up slightly to prevent loss m_dst->write( fileWi.posType ); m_dst->write( fileWi.posIndex ); m_dst->write( fileWi.infIndex ); m_dst->write( fileWi.infType ); m_dst->write( fileWi.infWeight ); } } log_debug( "wrote %d weighted influences\n", count ); } // Texture Projections if ( doWrite[ MDT_TexProjections ] ) { _setOffset( MDT_TexProjections, m_dst->offset(), offsetList ); _setUniformOffset( MDT_TexProjections, true, offsetList ); unsigned count = model->getProjectionCount(); writeHeaderB( 0x0000, count, FILE_TEXTURE_PROJECTION_SIZE ); for ( unsigned p = 0; p < count; p++ ) { uint16_t flags = 0x0000; m_dst->write( flags ); char name[40]; PORT_snprintf( name, sizeof(name), "%s", model->getProjectionName( p ) ); utf8chrtrunc( name, sizeof(name)-1 ); m_dst->writeBytes( (const uint8_t *) name, sizeof(name) ); int32_t type = model->getProjectionType( p ); m_dst->write( type ); double coord[3] = { 0, 0, 0 }; float fcoord[3] = { 0.0f, 0.0f, 0.0f }; model->getProjectionCoords( p, coord ); fcoord[0] = coord[0]; fcoord[1] = coord[1]; fcoord[2] = coord[2]; m_dst->write( fcoord[0] ); m_dst->write( fcoord[1] ); m_dst->write( fcoord[2] ); model->getProjectionUp( p, coord ); fcoord[0] = coord[0]; fcoord[1] = coord[1]; fcoord[2] = coord[2]; m_dst->write( fcoord[0] ); m_dst->write( fcoord[1] ); m_dst->write( fcoord[2] ); model->getProjectionSeam( p, coord ); fcoord[0] = coord[0]; fcoord[1] = coord[1]; fcoord[2] = coord[2]; m_dst->write( fcoord[0] ); m_dst->write( fcoord[1] ); m_dst->write( fcoord[2] ); double uv[2][2]; float fuv[2][2]; model->getProjectionRange( p, uv[0][0], uv[0][1], uv[1][0], uv[1][1] ); fuv[0][0] = uv[0][0]; fuv[0][1] = uv[0][1]; fuv[1][0] = uv[1][0]; fuv[1][1] = uv[1][1]; m_dst->write( fuv[0][0] ); m_dst->write( fuv[0][1] ); m_dst->write( fuv[1][0] ); m_dst->write( fuv[1][1] ); } log_debug( "wrote %d texture projections\n", count ); } // Skel Anims if ( doWrite[ MDT_SkelAnims ] ) { _setOffset( MDT_SkelAnims, m_dst->offset(), offsetList ); _setUniformOffset( MDT_SkelAnims, false, offsetList ); unsigned count = modelSkels.size(); writeHeaderA( 0x0000, count ); unsigned baseSize = sizeof(uint16_t) + sizeof(float32_t) + sizeof(uint32_t); for ( unsigned s = 0; s < count; s++ ) { Model::SkelAnim * sa = modelSkels[s]; unsigned animSize = baseSize + sa->m_name.length() + 1; uint32_t frameCount = sa->m_frameCount; uint32_t keyframeCount = 0; unsigned f = 0; for ( f = 0; f < frameCount; f++ ) { for ( unsigned j = 0; j < sa->m_jointKeyframes.size(); j++ ) { for ( unsigned k = 0; k < sa->m_jointKeyframes[j].size(); k++ ) { if ( sa->m_jointKeyframes[j][k]->m_frame == f ) { keyframeCount++; } } } } animSize += frameCount * sizeof(uint32_t); animSize += keyframeCount * FILE_SKEL_KEYFRAME_SIZE; uint16_t flags = 0x0000; float32_t fps = sa->m_fps; animSize = animSize; m_dst->write( animSize ); m_dst->write( flags ); m_dst->writeBytes( (const uint8_t *) sa->m_name.c_str(), sa->m_name.length() + 1 ); m_dst->write( fps ); uint32_t temp32 = frameCount; m_dst->write( temp32 ); for ( f = 0; f < frameCount; f++ ) { keyframeCount = 0; unsigned j = 0; for ( j = 0; j < sa->m_jointKeyframes.size(); j++ ) { for ( unsigned k = 0; k < sa->m_jointKeyframes[j].size(); k++ ) { if ( sa->m_jointKeyframes[j][k]->m_frame == f ) { keyframeCount++; } } } temp32 = keyframeCount; m_dst->write( temp32 ); unsigned written = 0; for ( j = 0; j < sa->m_jointKeyframes.size(); j++ ) { for ( unsigned k = 0; k < sa->m_jointKeyframes[j].size(); k++ ) { Model::Keyframe * kf = sa->m_jointKeyframes[j][k]; if ( kf->m_frame == f ) { MM3DFILE_SkelKeyframeT fileKf; fileKf.jointIndex = j; fileKf.keyframeType = kf->m_isRotation ? 0 : 1; fileKf.param[0] = kf->m_parameter[0]; fileKf.param[1] = kf->m_parameter[1]; fileKf.param[2] = kf->m_parameter[2]; m_dst->write( fileKf.jointIndex ); m_dst->write( fileKf.keyframeType ); m_dst->write( fileKf.param[0] ); m_dst->write( fileKf.param[1] ); m_dst->write( fileKf.param[2] ); written++; } } } } } log_debug( "wrote %d skel anims\n", count ); } // Frame Anims if ( doWrite[ MDT_FrameAnims ] ) { _setOffset( MDT_FrameAnims, m_dst->offset(), offsetList ); _setUniformOffset( MDT_FrameAnims, false, offsetList ); unsigned count = modelFrames.size(); writeHeaderA( 0x0000, count ); unsigned baseSize = sizeof(uint16_t) + sizeof(float32_t) + sizeof(uint32_t); for ( unsigned a = 0; a < count; a++ ) { Model::FrameAnim * fa = modelFrames[a]; unsigned animSize = baseSize + fa->m_name.length() + 1; uint32_t frameCount = fa->m_frameData.size(); unsigned vcount = modelVertices.size(); animSize += frameCount * vcount * sizeof(float32_t) * 3; uint16_t flags = 0x0000; float32_t fps = fa->m_fps; m_dst->write( animSize ); m_dst->write( flags ); m_dst->writeBytes( (const uint8_t *) fa->m_name.c_str(), fa->m_name.length() + 1 ); m_dst->write( fps ); uint32_t temp32 = frameCount; m_dst->write( temp32 ); for ( unsigned f = 0; f < frameCount; f++ ) { Model::FrameAnimVertexList * list = fa->m_frameData[f]->m_frameVertices; unsigned avcount = list->size(); log_debug( "vcount = %d, avcount = %d, size = %d\n", vcount, avcount, animSize ); for ( unsigned v = 0; v < vcount; v++ ) { if ( v < avcount ) { for ( unsigned i = 0; i < 3; i++ ) { float32_t coord = (*list)[v]->m_coord[i]; m_dst->write( coord ); } } else { m_dst->write( 0.0f ); m_dst->write( 0.0f ); m_dst->write( 0.0f ); } } } } log_debug( "wrote %d frame anims\n", count ); } // Frame Anim Points if ( doWrite[ MDT_FrameAnimPoints ] ) { _setOffset( MDT_FrameAnimPoints, m_dst->offset(), offsetList ); _setUniformOffset( MDT_FrameAnimPoints, false, offsetList ); unsigned count = modelFrames.size(); writeHeaderA( 0x0000, count ); unsigned baseSize = sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint32_t); unsigned pcount = model->getPointCount(); for ( unsigned a = 0; a < count; a++ ) { Model::FrameAnim * fa = modelFrames[a]; uint32_t frameCount = fa->m_frameData.size(); uint32_t animSize = baseSize + frameCount * (pcount * 6 * sizeof(float32_t)); uint16_t flags = 0x0000; uint32_t anim = a; m_dst->write( animSize ); m_dst->write( flags ); m_dst->write( anim ); m_dst->write( frameCount ); for ( unsigned f = 0; f < frameCount; f++ ) { Model::FrameAnimPointList * list = fa->m_frameData[f]->m_framePoints; unsigned apcount = list->size(); for ( unsigned p = 0; p < pcount; p++ ) { unsigned i; if ( p < apcount ) { for ( i = 0; i < 3; i++ ) { float32_t rot = (*list)[p]->m_rot[i]; m_dst->write( rot ); } for ( i = 0; i < 3; i++ ) { float32_t trans = (*list)[p]->m_trans[i]; m_dst->write( trans ); } } else { // rot m_dst->write( 0.0f ); m_dst->write( 0.0f ); m_dst->write( 0.0f ); // trans m_dst->write( 0.0f ); m_dst->write( 0.0f ); m_dst->write( 0.0f ); } } } } log_debug( "wrote %d frame anim points\n", count ); } // Write unknown data (add dirty flag to offset type) for ( f = 0; f < formatDataCount; f++ ) { Model::FormatData * fd = model->getFormatData( f ); uint16_t thisType = (fd->offsetType | OFFSET_DIRTY_MASK); if ( fd->offsetType != 0 ) { MisfitOffsetList::iterator it; for ( it = offsetList.begin(); it != offsetList.end(); it++ ) { if ( (*it).offsetType == thisType ) { (*it).offsetValue = m_dst->offset(); log_warning( "setting uknown data type %04x offset at %08x\n", (*it).offsetType, (*it).offsetValue ); m_dst->writeBytes( (const uint8_t *) fd->data, fd->len ); break; } } } } // Re-write header with offsets _setOffset( MDT_EndOfFile, m_dst->offset(), offsetList ); m_dst->seek(12); for ( t = 0; t < offsetCount; t++ ) { MisfitOffsetT & mo = offsetList[t]; m_dst->write( mo.offsetType ); m_dst->write( mo.offsetValue ); } log_debug( "wrote %d updated offsets\n", offsetCount ); return Model::ERROR_NONE; } bool MisfitFilter::canRead( const char * filename ) { return true; } bool MisfitFilter::canWrite( const char * filename ) { return true; } bool MisfitFilter::canExport( const char * filename ) { return true; } bool MisfitFilter::isSupported( const char * filename ) { unsigned len = strlen( filename ); if ( len >= 5 && strcasecmp( &filename[len-5], ".mm3d" ) == 0 ) { return true; } else { return false; } } list< string > MisfitFilter::getReadTypes() { list rval; rval.push_back( "*.mm3d" ); return rval; } list< string > MisfitFilter::getWriteTypes() { list rval; rval.push_back( "*.mm3d" ); return rval; } void MisfitFilter::writeHeaderA( uint16_t flags, uint32_t count ) { m_dst->write( flags ); m_dst->write( count ); } void MisfitFilter::writeHeaderB( uint16_t flags, uint32_t count, uint32_t size ) { m_dst->write( flags ); m_dst->write( count ); m_dst->write( size ); } void MisfitFilter::readHeaderA( uint16_t & flags, uint32_t & count ) { m_src->read( flags ); m_src->read( count ); } void MisfitFilter::readHeaderB( uint16_t & flags, uint32_t & count, uint32_t & size ) { m_src->read( flags ); m_src->read( count ); m_src->read( size ); } mm3d-1.3.7/src/libmm3d/Makefile.in0000644000175000017500000004703611025503557013503 00000000000000# Makefile.in generated by automake 1.9.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ top_builddir = ../.. am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd INSTALL = @INSTALL@ install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = src/libmm3d DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libmm3d_a_AR = $(AR) $(ARFLAGS) libmm3d_a_LIBADD = am__objects_1 = am_libmm3d_a_OBJECTS = bsptree.$(OBJEXT) cal3dfilter.$(OBJEXT) \ cmdlinemgr.$(OBJEXT) cobfilter.$(OBJEXT) datadest.$(OBJEXT) \ filedatadest.$(OBJEXT) memdatadest.$(OBJEXT) \ datasource.$(OBJEXT) filedatasource.$(OBJEXT) \ memdatasource.$(OBJEXT) dxffilter.$(OBJEXT) \ filefactory.$(OBJEXT) filtermgr.$(OBJEXT) glmath.$(OBJEXT) \ log.$(OBJEXT) lwofilter.$(OBJEXT) mesh.$(OBJEXT) \ misc.$(OBJEXT) mlocale.$(OBJEXT) model.$(OBJEXT) \ model_anim.$(OBJEXT) model_bool.$(OBJEXT) model_copy.$(OBJEXT) \ model_draw.$(OBJEXT) model_group.$(OBJEXT) \ model_influence.$(OBJEXT) model_inner.$(OBJEXT) \ model_insert.$(OBJEXT) model_meta.$(OBJEXT) \ model_ops.$(OBJEXT) model_print.$(OBJEXT) model_proj.$(OBJEXT) \ model_select.$(OBJEXT) model_texture.$(OBJEXT) \ modelfilter.$(OBJEXT) modelstatus.$(OBJEXT) \ modelundo.$(OBJEXT) modelutil.$(OBJEXT) md2filter.$(OBJEXT) \ md3filter.$(OBJEXT) mm3dfilter.$(OBJEXT) \ mm3dfilter_ref.$(OBJEXT) mm3dreg.$(OBJEXT) mm3dport.$(OBJEXT) \ ms3dfilter.$(OBJEXT) msg.$(OBJEXT) objfilter.$(OBJEXT) \ texmgr.$(OBJEXT) texscale.$(OBJEXT) texture.$(OBJEXT) \ triprim.$(OBJEXT) translate.$(OBJEXT) undo.$(OBJEXT) \ undomgr.$(OBJEXT) weld.$(OBJEXT) pcxtex.$(OBJEXT) \ rawtex.$(OBJEXT) tgatex.$(OBJEXT) txtfilter.$(OBJEXT) \ $(am__objects_1) libmm3d_a_OBJECTS = $(am_libmm3d_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libmm3d_a_SOURCES) DIST_SOURCES = $(libmm3d_a_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BYTEORDER = @BYTEORDER@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CORE_PROFILE = @CORE_PROFILE@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLOPEN_LIBS = @DLOPEN_LIBS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GL_CFLAGS = @GL_CFLAGS@ GL_LIBS = @GL_LIBS@ GREP = @GREP@ HAVE_QT4 = @HAVE_QT4@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ LUALIB_CCFLAGS = @LUALIB_CCFLAGS@ LUALIB_DIR = @LUALIB_DIR@ LUALIB_LIBS = @LUALIB_LIBS@ LUA_CCFLAGS = @LUA_CCFLAGS@ LUA_DIR = @LUA_DIR@ LUA_LIBS = @LUA_LIBS@ MAKEINFO = @MAKEINFO@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PROFILE = @PROFILE@ QGL_LIBS = @QGL_LIBS@ QT_CXXFLAGS = @QT_CXXFLAGS@ QT_DIR = @QT_DIR@ QT_LIBS = @QT_LIBS@ QT_LRELEASE = @QT_LRELEASE@ QT_MOC = @QT_MOC@ QT_UIC = @QT_UIC@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ XMKMF = @XMKMF@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ noinst_LIBRARIES = libmm3d.a libmm3d_HFILES = \ binutil.h \ bsptree.h \ cal3dfilter.h \ cmdlinemgr.h \ cobfilter.h \ datadest.h \ filedatadest.h \ memdatadest.h \ datasource.h \ filedatasource.h \ memdatasource.h \ drawcontext.h \ dxffilter.h \ endianconfig.h \ file_closer.h \ filefactory.h \ filtermgr.h \ glheaders.h \ glmath.h \ local_array.h \ local_ptr.h \ log.h \ lwofilter.h \ md2filter-anorms.h \ md2filter.h \ md3filter.h \ mesh.h \ misc.h \ mlocale.h \ mm3dconfig.h \ mm3dfilter.h \ mm3dfilter_ref.h \ mm3dport.h \ mm3dreg.h \ mm3dtypes.h \ model.h \ modelfilter.h \ modelstatus.h \ modelundo.h \ modelutil.h \ ms3dfilter.h \ msg.h \ objfilter.h \ pcxtex.h \ rawtex.h \ release_ptr.h \ sorted_list.h \ texmgr.h \ texscale.h \ texture.h \ tgatex.h \ triprim.h \ translate.h \ txtfilter.h \ undo.h \ undomgr.h \ util.h \ weld.h libmm3d_a_SOURCES = \ bsptree.cc \ cal3dfilter.cc \ cmdlinemgr.cc \ cobfilter.cc \ datadest.cc \ filedatadest.cc \ memdatadest.cc \ datasource.cc \ filedatasource.cc \ memdatasource.cc \ dxffilter.cc \ filefactory.cc \ filtermgr.cc \ glmath.cc \ log.cc \ lwofilter.cc \ mesh.cc \ misc.cc \ mlocale.cc \ model.cc model_anim.cc model_bool.cc model_copy.cc model_draw.cc model_group.cc model_influence.cc model_inner.cc model_insert.cc model_meta.cc model_ops.cc model_print.cc model_proj.cc model_select.cc model_texture.cc \ modelfilter.cc \ modelstatus.cc \ modelundo.cc \ modelutil.cc \ md2filter.cc \ md3filter.cc \ mm3dfilter.cc \ mm3dfilter_ref.cc \ mm3dreg.cc \ mm3dport.cc \ ms3dfilter.cc \ msg.cc \ objfilter.cc \ texmgr.cc \ texscale.cc \ texture.cc \ triprim.cc \ translate.cc \ undo.cc \ undomgr.cc \ weld.cc \ pcxtex.cc \ rawtex.cc \ tgatex.cc \ txtfilter.cc \ $(libmm3d_HFILES) AM_CPPFLAGS = $(CORE_PROFILE) -coverage -Wall -I.. -DMM3D_EDIT $(all_includes) $(GL_CFLAGS) CLEANFILES = *.gcno *.gcda all: all-am .SUFFIXES: .SUFFIXES: .cc .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libmm3d/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu src/libmm3d/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libmm3d.a: $(libmm3d_a_OBJECTS) $(libmm3d_a_DEPENDENCIES) -rm -f libmm3d.a $(libmm3d_a_AR) libmm3d.a $(libmm3d_a_OBJECTS) $(libmm3d_a_LIBADD) $(RANLIB) libmm3d.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bsptree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cal3dfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmdlinemgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cobfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datadest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datasource.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dxffilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filedatadest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filedatasource.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filefactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filtermgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glmath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lwofilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md2filter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md3filter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memdatadest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memdatasource.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mesh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mlocale.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mm3dfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mm3dfilter_ref.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mm3dport.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mm3dreg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_anim.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_bool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_copy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_draw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_group.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_influence.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_inner.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_insert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_meta.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_ops.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_print.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_proj.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_select.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model_texture.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modelfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modelstatus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modelundo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modelutil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ms3dfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcxtex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rawtex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texmgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texscale.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texture.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tgatex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/translate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/triprim.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/txtfilter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/undo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/undomgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/weld.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ @am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) ' { files[$$0] = 1; } \ END { for (i in files) print i; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ esac; \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ if test "$$dir" != "$$file" && test "$$dir" != "."; then \ dir="/$$dir"; \ $(mkdir_p) "$(distdir)$$dir"; \ else \ dir=''; \ fi; \ if test -d $$d/$$file; then \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-exec-am: install-info: install-info-am install-man: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-info-am .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-exec install-exec-am install-info \ install-info-am install-man install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-info-am wc: wc `ls *.h *.cpp *.cc *.y *.l 2> /dev/null | grep -v moc.cc | grep -v "\.base\." ` | sort -n # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: mm3d-1.3.7/src/libmm3d/modelfilter.cc0000644000175000017500000000457110744511346014252 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "modelfilter.h" #include "datasource.h" #include "datadest.h" #include "log.h" #include #include int ModelFilter::Options::s_allocated = 0; ModelFilter::ModelFilter() : m_optionsFunc( NULL ), m_defaultFactory(), m_factory( &m_defaultFactory ) { } ModelFilter::Options::Options() { s_allocated++; } ModelFilter::Options::~Options() { s_allocated--; } void ModelFilter::Options::stats() { log_debug( "Filter Options: %d\n", s_allocated ); } DataSource * ModelFilter::openInput( const char * filename, Model::ModelErrorE & err ) { DataSource * src = m_factory->getSource( filename ); if ( src->errorOccurred() ) { if ( src->unexpectedEof() ) err = Model::ERROR_UNEXPECTED_EOF; else err = errnoToModelError( src->getErrno() ); } return src; } DataDest * ModelFilter::openOutput( const char * filename, Model::ModelErrorE & err ) { DataDest * dst = m_factory->getDest( filename ); if ( dst->errorOccurred() ) { if ( dst->atFileLimit() ) err = Model::ERROR_UNEXPECTED_EOF; else err = errnoToModelError( dst->getErrno() ); } return dst; } /* static */ Model::ModelErrorE ModelFilter::errnoToModelError( int err ) { switch ( err ) { case EACCES: case EPERM: return Model::ERROR_NO_ACCESS; case ENOENT: case EBADF: return Model::ERROR_NO_FILE; case EISDIR: return Model::ERROR_BAD_DATA; default: break; } return Model::ERROR_FILE_OPEN; } mm3d-1.3.7/src/libmm3d/cal3dfilter.h0000644000175000017500000001501111000471707013761 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __CAL3DFILTER_H #define __CAL3DFILTER_H #include "modelfilter.h" #include "mesh.h" #include #include #include #include #include #include #include class Cal3dFilter : public ModelFilter { public: // The default values for the filter options are in // the constructor. class Cal3dOptions : public ModelFilter::Options { public: Cal3dOptions(); bool m_singleMeshFile; bool m_xmlMatFile; void setOptionsFromModel( Model * m ); protected: virtual ~Cal3dOptions(); // Use release() instead }; Cal3dFilter(); virtual ~Cal3dFilter(); Model::ModelErrorE readFile( Model * model, const char * const filename ); Model::ModelErrorE writeFile( Model * model, const char * const filename, ModelFilter::Options * o ); bool canRead( const char * filename ); bool canWrite( const char * filename ); bool canExport( const char * filename ); bool isSupported( const char * filename ); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); ModelFilter::Options * getDefaultOptions() { return new Cal3dOptions; }; struct _UVData_t { float u; float v; }; typedef struct _UVData_t UVDataT; typedef std::vector< UVDataT > UVList; protected: enum _FileType_e { FT_Any, FT_Skeleton, FT_Animation, FT_Mesh, FT_Material, FT_MAX, }; typedef enum _FileType_e FileTypeE; static bool listHas( const std::list & l, const std::string & val ); static std::string addExtension( const std::string file, const std::string ext ); static bool versionIsValid( FileTypeE type, int version ); static bool xversionIsValid( FileTypeE type, int version ); // Sub file reads Model::ModelErrorE readSubFile( const char * filename ); Model::ModelErrorE readXSubFile( uint8_t * buf, size_t len ); Model::ModelErrorE readCal3dFile( uint8_t * buf, size_t len ); Model::ModelErrorE readSkeletonFile( uint8_t * buf, size_t len ); Model::ModelErrorE readMeshFile( uint8_t * buf, size_t len ); Model::ModelErrorE readMaterialFile( uint8_t * buf, size_t len ); Model::ModelErrorE readXMaterialFile( uint8_t * buf, size_t len ); Model::ModelErrorE readAnimationFile( uint8_t * buf, size_t len ); // Common read functions Model::ModelErrorE readFileToBuffer( const char * filename, uint8_t * & buf, size_t & len ); void freeFileBuffer( uint8_t * buf ); uint8_t readBUInt8(); int16_t readBInt16(); int32_t readBInt32(); uint64_t readBUInt48(); float readBFloat(); Vector readBVector3(); Vector readBVector4(); bool readBString( std::string & ); bool readBLine( std::string &, size_t maxLen ); // common XML reading functions bool findXElement( const char * tag ); // Finds an XML element by tag std::string readXAttribute( const char * attr ); // Read a specified attribute of the current element std::string readXElement( const char * tag ); // Read the contents of the XML tag (if any) Vector readAVector3( const char * str ); Vector readAVector4( const char * str ); std::string readAString( const char * str ); bool readBBone(); bool readBSubMesh(); bool readBAnimTrack(); bool readBCompressedAnimTrack( double duration ); std::string readLineKey( const char * str ); std::string readLineFile( const char * str ); // binary sub file writes Model::ModelErrorE writeCal3dFile( const char * filename, Model * model, ModelFilter::Options * o ); Model::ModelErrorE writeSkeletonFile( const char * filename, Model * model ); Model::ModelErrorE writeMeshFile( const char * filename, Model * model ); Model::ModelErrorE writeMeshListFile( const char * filename, Model * model, const MeshList & meshList ); Model::ModelErrorE writeMaterialFile( const char * filename, Model * model, unsigned int materialId ); Model::ModelErrorE writeAnimationFile( const char * filename, Model * model, unsigned int animationId ); // XML sub file writes Model::ModelErrorE writeXMaterialFile( const char * filename, Model * model, unsigned int materialId ); // Common binary write functions void writeBVector3( const Vector & vec ); void writeBQuaternion( const Quaternion & quat ); void writeBString( const std::string & ); void writeBColor( const float * fval ); void writeBBone( unsigned int b ); void writeBAnimTrack( unsigned int anim, unsigned int bone ); void writeBMesh( const Mesh & mesh ); // Common XML write functions void writeXColor( const char * tag, const float * fval ); int timeToFrame( double tsec, double fps ); int findAnimation( const std::string& animName ); Model * m_model; Cal3dOptions * m_options; DataDest * m_dst; uint8_t * m_bufPos; uint8_t * m_fileBuf; size_t m_fileLength; int m_anim; bool m_isBinary; bool m_isLittleEndian; int m_maxBinaryVersion; int m_maxXrfVersion; std::string m_modelPath; std::string m_modelBaseName; std::string m_modelFullName; std::string m_currentPath; std::string m_modelPartName; std::string m_modelPartExt; std::list m_formats; }; #endif // __CAL3DFILTER_H mm3d-1.3.7/src/libmm3d/cmdlinemgr.cc0000644000175000017500000001465010744511346014064 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "cmdlinemgr.h" #include namespace { class FunctionOption : public CommandLineManager::Option { public: FunctionOption( char shortOption, const char * longOption, bool takesArg, CommandLineManager::OptionFunctionF optFunc ) : CommandLineManager::Option( shortOption, longOption, NULL, takesArg ), m_optFunc( optFunc ) { } virtual ~FunctionOption() { } void customParse( const char * arg ) { if ( m_optFunc ) m_optFunc( arg ); } private: CommandLineManager::OptionFunctionF m_optFunc; }; } // namespace CommandLineManager::Option::Option( char shortOption, const char * longOption, const char * defaultValue, bool takesArg ) : m_shortOption( shortOption ), m_longOption( longOption ), m_takesArg( takesArg ), m_isSpecified( false ), m_intValue( 0 ), m_stringValue( "" ) { if ( defaultValue ) { m_stringValue = defaultValue; m_intValue = atoi( defaultValue ); } } CommandLineManager::Option::~Option() { } void CommandLineManager::Option::parseOption( const char * arg ) { if ( arg ) { m_isSpecified = true; m_stringValue = arg; m_intValue = atoi( arg ); customParse( arg ); } } void CommandLineManager::Option::customParse( const char * arg ) { // Do nothing } CommandLineManager::CommandLineManager() : m_uniqueId( 0 ), m_firstArg( 1 ), m_error( NoError ), m_errorArg( 0 ) { } CommandLineManager::~CommandLineManager() { } bool CommandLineManager::parse( int argc, const char ** argv ) { for ( int a = 1; a < argc; a++ ) { const char * str = argv[a]; // If this string doesn't start with a dash, or is just a single // dash (stdin as file input), then we're done. if ( str[0] != '-' || str[1] == '\0' ) { m_firstArg = a; return true; } if ( strcmp("--", str) == 0 ) { // End of options m_firstArg = a + 1; return true; } Option * opt = NULL; const char * arg = NULL; int nextOpt = a; // It is an option if ( str[1] == '-' ) { // Long option std::string longOpt = &str[2]; const char * end = strchr( str, '=' ); if ( end ) { arg = end + 1; longOpt.resize( end - &str[2] ); } else { arg = argv[a+1]; nextOpt = a + 1; } opt = lookupOptionByLong( longOpt.c_str() ); } else { // Short option const char * end = strchr( str, '=' ); if ( end ) { arg = end + 1; } else { arg = argv[a+1]; nextOpt = a + 1; } opt = lookupOptionByShort( str[1] ); } if ( !opt ) { m_error = UnknownOption; m_errorArg = a; return false; } if ( opt->takesArgument() ) { a = nextOpt; if ( a >= argc ) { m_error = MissingArgument; m_errorArg = a - 1; return false; } } else { arg = ""; } opt->parseOption( arg ); } // Ran out of command line options, there are no arguments m_firstArg = argc; return true; } void CommandLineManager::addOption( int id, char shortOption, const char * longOption, const char * defaultValue, bool takesArg ) { m_optionList[ id ] = new Option( shortOption, longOption, defaultValue, takesArg ); } void CommandLineManager::addCustomOption( int id, Option * opt ) { m_optionList[ id ] = opt; } void CommandLineManager::addFunctionOption( int id, char shortOption, const char * longOption, bool takesArg, OptionFunctionF optFunc ) { m_optionList[ id ] = new FunctionOption( shortOption, longOption, takesArg, optFunc ); } bool CommandLineManager::isSpecified( int optionId ) const { const Option * opt = lookupOptionById( optionId ); if ( opt ) return opt->isSpecified(); return false; } int CommandLineManager::intValue( int optionId ) const { const Option * opt = lookupOptionById( optionId ); if ( opt ) return opt->intValue(); return 0; } const char * CommandLineManager::stringValue( int optionId ) const { const Option * opt = lookupOptionById( optionId ); if ( opt ) return opt->stringValue(); return ""; } int CommandLineManager::getUniqueId() { return --m_uniqueId; } const CommandLineManager::Option * CommandLineManager::lookupOptionById( int optionId ) const { OptionListT::const_iterator it = m_optionList.find( optionId ); if ( it != m_optionList.end() ) return it->second.get(); else return NULL; } CommandLineManager::Option * CommandLineManager::lookupOptionByShort( char shortOption ) { for ( OptionListT::iterator it = m_optionList.begin(); it != m_optionList.end(); ++it ) { const char opt = it->second->shortOption(); if ( opt != 0 && opt == shortOption ) { return it->second.get(); } } return NULL; } CommandLineManager::Option * CommandLineManager::lookupOptionByLong( const char * longOption ) { for ( OptionListT::iterator it = m_optionList.begin(); it != m_optionList.end(); ++it ) { const char * opt = it->second->longOption(); if ( opt && strcmp( opt, longOption ) == 0 ) { return it->second.get(); } } return NULL; } mm3d-1.3.7/src/libmm3d/mm3dfilter_ref.cc0000644000175000017500000016347711025050654014652 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "mm3dfilter_ref.h" //----------------------------------------------------------------------------- // Begin reference code //----------------------------------------------------------------------------- #include "model.h" #include "texture.h" #include "log.h" #include "binutil.h" #include "misc.h" #include "endianconfig.h" #include "mm3dport.h" #include "msg.h" #include "translate.h" #include #include #include #include #include using std::list; using std::string; const char MisfitFilterRef::MAGIC[] = "MISFIT3D"; const uint8_t MisfitFilterRef::WRITE_VERSION_MAJOR = 0x01; const uint8_t MisfitFilterRef::WRITE_VERSION_MINOR = 0x05; // FIXME bump version const uint16_t MisfitFilterRef::OFFSET_TYPE_MASK = 0x3fff; const uint16_t MisfitFilterRef::OFFSET_UNI_MASK = 0x8000; const uint16_t MisfitFilterRef::OFFSET_DIRTY_MASK = 0x4000; namespace { // Misfit MM3D format: // // File Header // // MAGIC_NUMBER 8 bytes "MISFIT3D" // MAJOR_VERSION uint8 0x01 // MINOR_VERSION uint8 0x05 // MODEL_FLAGS uint8 0x00 (reserved) // OFFSET_COUNT uint8 [offc] // // [OFFSET_COUNT] instances of: // Offset header list // OFFSET_HEADER 6 bytes * [offc] // // Offset Header // OFFSET_TYPE uint16 (highest bit 0 = Data type A, 1 = data type B) // OFFSET_VALUE uint32 // // Data header A (Variable data size) // DATA_FLAGS uint16 // DATA_COUNT uint32 // // Data block A // // [DATA_COUNT] instances of: // DATA_SIZE uint32 bytes // DATA_BLOCK_A [DATA_SIZE] bytes // // Data header B (Uniform data size) // DATA_FLAGS uint16 // DATA_COUNT uint32 // DATA_SIZE uint32 // // Data block B // // [DATA_COUNT] instances of: // DATA_BLOCK_B [DATA_SIZE] bytes // // // Offset A types: // 0x1001 Meta information // 0x1002 Unknown type information // 0x0101 Groups // 0x0141 Embedded textures // 0x0142 External textures // 0x0161 Materials // 0x016c Texture Projection Triangles // 0x0191 Canvas background images // // 0x0301 Skeletal Animations // 0x0321 Frame Animations // 0x0326 Frame Animation Points // 0x0341 Frame Relative Animations // // Offset B types: // 0x0001 Vertices // 0x0021 Triangles // 0x0026 Triangle Normals // 0x0041 Joints // 0x0046 Joint Vertices // 0x0061 Points // 0x0106 Smooth Angles // 0x0168 Texture Projections // 0x0121 Texture Coordinates // // // // Meta information data // KEY ASCIIZ <= 1024 (may not be empty) // VALUE ASCIIZ <= 1024 (may be empty) // // Unknown type information // OFFSET_TYPE uint16 // INFO_STRING ASCIIZ <= 256 (inform user how to support this data) // // // Vertex data // FLAGS uint16 // X_COORD float32 // Y_COORD float32 // Z_COORD float32 // // // Triangle data // FLAGS uint16 // VERTEX1_INDEX uint32 // VERTEX2_INDEX uint32 // VERTEX3_INDEX uint32 // // Group data // FLAGS uint16 // NAME ASCIIZ <= inf // TRI_COUNT uint32 // TRI_INDICES uint32 * [TRI_COUNT] // SMOOTHNESS uint8 // MATERIAL_INDEX uint32 // // Smooth Angles (maximum angle between smoothed normals for a group) // GROUP_INDEX uint32 // SMOOTHNESS uint8 // // Weighted Influences // POS_TYPE uint8 // POS_INDEX uint32 // INF_INDEX uint32 // INF_TYPE uint8 // INF_WEIGHT uint8 // // External texture data // FLAGS uint16 // FILENAME ASCIIZ // // Embedded texture data // FLAGS uint16 // FORMAT char8 * 4 ('JPEG', 'PNG ', 'TGA ', etc...) // TEXTURE_SIZE uint32 // DATA uint8 * [TEXTURE_SIZE] // // Material // FLAGS uint16 // TEXTURE_INDEX uint32 // NAME ASCIIZ // AMBIENT float32 * 4 // DIFFUSE float32 * 4 // SPECULAR float32 * 4 // EMISSIVE float32 * 4 // SHININESS float32 // // Projection Triangles // PROJECTION_INDEX uint32 // TRI_COUNT uint32 // TRI_INDICES uint32 * [TRI_COUNT] // // Canvas background image // FLAGS uint16 // VIEW_INDEX uint8 // SCALE float32 // CENTER_X float32 // CENTER_X float32 // CENTER_X float32 // FILENAME ASCIIZ // // Texture coordinates // FLAGS uint16 // TRI_INDEX uint32 // COORD_S float32 * 3 // COORD_T float32 * 3 // // Joint data // FLAGS uint16 // NAME char8 * 40 // PARENT_INDEX int32 // LOCAL_ROT float32 * 3 // LOCAL_TRANS float32 * 3 // // Joint Vertices // VERTEX_INDEX uint32 // JOINT_INDEX int32 // // Point data // FLAGS uint16 // NAME char8 * 40 // TYPE int32 // BONE_INDEX int32 // ROTATION float32 * 3 // TRANSLATION float32 * 3 // // Texture Projection // FLAGS uint16 // NAME char8 * 40 // TYPE int32 // POSITION float32 * 3 // UP VECTOR float32 * 3 // SEAM VECTOR float32 * 3 // U MIN float32 // V MIN float32 // U MAX float32 // V MAX float32 // // Skeletal animation // FLAGS uint16 // NAME ASCIIZ // FPS float32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // KEYFRAME_COUNT uint32 // // [KEYFRAME_COUNT] instances of: // JOINT_INDEX uint32 // KEYFRAME_TYPE uint8 (0 = rotation, 1 = translation) // PARAM float32 * 3 // // Frame animation // FLAGS uint16 // NAME ASCIIZ <= 64 // FPS float32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // // [VERTEX_COUNT] instances of: // COORD_X float32 // COORD_Y float32 // COORD_Z float32 // // Frame animation points // FLAGS uint16 // FRAME_ANIM_INDEX uint32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // // [POINT_COUNT] instances of: // ROT_X float32 // ROT_Y float32 // ROT_Z float32 // TRANS_X float32 // TRANS_Y float32 // TRANS_Z float32 // // Frame relative animation // FLAGS uint16 // NAME ASCIIZ <= 64 // FPS float32 // FRAME_COUNT uint32 // // [FRAME_COUNT] instances of: // FVERT_COUNT uint32 // // [FVERT_COUNT] instances of: // VERTEX_INDEX // COORD_X_OFFSET float32 // COORD_Y_OFFSET float32 // COORD_Z_OFFSET float32 // typedef struct _MisfitOffset_t { uint16_t offsetType; uint32_t offsetValue; } MisfitOffsetT; typedef std::vector MisfitOffsetList; typedef enum _MisfitDataTypes_e { // A Types MDT_Meta, MDT_TypeInfo, MDT_Groups, MDT_EmbTextures, MDT_ExtTextures, MDT_Materials, MDT_ProjectionTriangles, MDT_CanvasBackgrounds, MDT_SkelAnims, MDT_FrameAnims, MDT_FrameAnimPoints, MDT_RelativeAnims, // B Types MDT_Vertices, MDT_Triangles, MDT_TriangleNormals, MDT_Joints, MDT_JointVertices, MDT_Points, MDT_SmoothAngles, MDT_WeightedInfluences, MDT_TexProjections, MDT_TexCoords, // End of list MDT_EndOfFile, MDT_MAX } MisfitDataTypesE; typedef enum _MisfitFlags_e { MF_HIDDEN = 1, // powers of 2 MF_SELECTED = 2, MF_VERTFREE = 4, // vertex does not have to be conntected to a face // Type-specific flags MF_MAT_CLAMP_S = 16, MF_MAT_CLAMP_T = 32 } MisfitFlagsE; static const uint16_t _misfitOffsetTypes[MDT_MAX] = { // Offset A types 0x1001, // Meta information 0x1002, // Unknown type information 0x0101, // Groups 0x0141, // Embedded textures 0x0142, // External textures 0x0161, // Materials 0x016c, // Texture Projection Triangles 0x0191, // Canvas background images 0x0301, // Skeletal Animations 0x0321, // Frame Animations 0x0326, // Frame Animation Points 0x0341, // Frame Relative Animations // Offset B types: 0x0001, // Vertices 0x0021, // Triangles 0x0026, // Triangle Normals 0x0041, // Joints 0x0046, // Joint Vertices 0x0061, // Points 0x0106, // Smooth Angles 0x0146, // Weighted Influences 0x0168, // Texture Projections 0x0121, // Texture Coordinates 0x3fff, // End of file }; static const char _misfitOffsetNames[MDT_MAX][30] = { // Offset A types "Meta information", "Type identity", "Groups", "Embedded textures", "External textures", "Materials", "Texture projection triangles", "Canvas background images", "Skeletal animations", "Frame animations", "Frame animation points", "Frame relative animations", // Offset B types "Vertices", "Triangles", "Triangle normals", "Joints", "Joint vertices", "Points", "Max smoothing angles", "Weighted Influences", "Texture projections", "Texture coordinates", // End of file "End of file" }; // File header struct _MM3DFILE_Header_t { char magic[8]; uint8_t versionMajor; uint8_t versionMinor; uint8_t modelFlags; uint8_t offsetCount; }; typedef struct _MM3DFILE_Header_t MM3DFILE_HeaderT; // Data header A (Variable data size) struct _MM3DFILE_DataHeaderA_t { uint16_t flags; uint32_t count; }; typedef struct _MM3DFILE_DataHeaderA_t MM3DFILE_DataHeaderAT; // Data header B (Uniform data size) struct _MM3DFILE_DataHeaderB_t { uint16_t flags; uint32_t count; uint32_t size; }; typedef struct _MM3DFILE_DataHeaderB_t MM3DFILE_DataHeaderBT; struct _MM3DFILE_Vertex_t { uint16_t flags; float32_t coord[3]; }; typedef struct _MM3DFILE_Vertex_t MM3DFILE_VertexT; const size_t FILE_VERTEX_SIZE = 14; struct _MM3DFILE_Triangle_t { uint16_t flags; uint32_t vertex[3]; }; typedef struct _MM3DFILE_Triangle_t MM3DFILE_TriangleT; const size_t FILE_TRIANGLE_SIZE = 14; struct _MM3DFILE_TriangleNormals_t { uint16_t flags; uint32_t index; float32_t normal[3][3]; }; typedef struct _MM3DFILE_TriangleNormals_t MM3DFILE_TriangleNormalsT; const size_t FILE_TRIANGLE_NORMAL_SIZE = 42; struct _MM3DFILE_Joint_t { uint16_t flags; char name[40]; int32_t parentIndex; float32_t localRot[3]; float32_t localTrans[3]; }; typedef struct _MM3DFILE_Joint_t MM3DFILE_JointT; const size_t FILE_JOINT_SIZE = 70; struct _MM3DFILE_JointVertex_t { uint32_t vertexIndex; int32_t jointIndex; }; typedef struct _MM3DFILE_JointVertex_t MM3DFILE_JointVertexT; const size_t FILE_JOINT_VERTEX_SIZE = 8; struct _MM3DFILE_WeightedInfluence_t { uint8_t posType; uint32_t posIndex; uint32_t infIndex; uint8_t infType; int8_t infWeight; }; typedef struct _MM3DFILE_WeightedInfluence_t MM3DFILE_WeightedInfluenceT; const size_t FILE_WEIGHTED_INFLUENCE_SIZE = 11; struct _MM3DFILE_Point_t { uint16_t flags; char name[40]; int32_t type; int32_t boneIndex; float32_t rot[3]; float32_t trans[3]; }; typedef struct _MM3DFILE_Point_t MM3DFILE_PointT; const size_t FILE_POINT_SIZE = 74; struct _MM3DFILE_SmoothAngle_t { uint32_t groupIndex; uint8_t angle; }; typedef struct _MM3DFILE_SmoothAngle_t MM3DFILE_SmoothAngleT; const size_t FILE_SMOOTH_ANGLE_SIZE = 5; struct _MM3DFILE_CanvasBackground_t { uint16_t flags; uint8_t viewIndex; float32_t scale; float32_t center[3]; }; typedef struct _MM3DFILE_CanvasBackground_t MM3DFILE_CanvasBackgroundT; const size_t FILE_CANVAS_BACKGROUND_SIZE = 19; struct _MM3DFILE_SkelKeyframe_t { uint32_t jointIndex; uint8_t keyframeType; float32_t param[3]; }; typedef struct _MM3DFILE_SkelKeyframe_t MM3DFILE_SkelKeyframeT; const size_t FILE_SKEL_KEYFRAME_SIZE = 17; struct _MM3DFILE_TexCoord_t { uint16_t flags; uint32_t triangleIndex; float32_t sCoord[3]; float32_t tCoord[3]; }; typedef struct _MM3DFILE_TexCoord_t MM3DFILE_TexCoordT; const size_t FILE_TEXCOORD_SIZE = 30; const size_t FILE_TEXTURE_PROJECTION_SIZE = 98; struct _UnknownData_t { uint16_t offsetType; uint32_t offsetValue; uint32_t dataLen; }; typedef struct _UnknownData_t UnknownDataT; typedef std::list UnknownDataList; bool _offsetIncluded( MisfitDataTypesE type, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilterRef::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { return true; } } return false; } unsigned _offsetGet( MisfitDataTypesE type, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilterRef::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { return list[n].offsetValue; } } return 0; } bool _offsetIsVariable( MisfitDataTypesE type, MisfitOffsetList & list ) { unsigned count = list.size(); for ( unsigned n = 0; n < count; n++ ) { if ( (list[n].offsetType & MisfitFilterRef::OFFSET_TYPE_MASK) == _misfitOffsetTypes[type] ) { return ((list[n].offsetType & MisfitFilterRef::OFFSET_UNI_MASK) == 0); } } return false; } } // namespace MisfitFilterRef::MisfitFilterRef() { } MisfitFilterRef::~MisfitFilterRef() { } Model::ModelErrorE MisfitFilterRef::readFile( Model * model, const char * const filename ) { if ( filename == NULL || filename[0] == '\0' ) { return Model::ERROR_BAD_ARGUMENT; } if ( sizeof( float32_t ) != 4 ) { msg_error( transll( QT_TRANSLATE_NOOP( "LowLevel", "MM3D encountered an unexpected data size problem\nSee Help->About to contact the developers" )).c_str() ); return Model::ERROR_FILE_OPEN; } m_fp = fopen( filename, "rb" ); if ( m_fp == NULL ) { switch ( errno ) { case EACCES: case EPERM: return Model::ERROR_NO_ACCESS; case ENOENT: return Model::ERROR_NO_FILE; case EISDIR: return Model::ERROR_BAD_DATA; default: return Model::ERROR_FILE_OPEN; } } string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); model->setFilename( modelFullName.c_str() ); fseek( m_fp, 0, SEEK_END ); unsigned fileLength = ftell( m_fp ); m_readLength = fileLength; fseek( m_fp, 0, SEEK_SET ); uint8_t * fileBuf = new uint8_t[fileLength]; m_bufPos = fileBuf; m_readLength = fileLength; fread( fileBuf, fileLength, 1, m_fp ); fclose( m_fp ); m_fp = NULL; MM3DFILE_HeaderT fileHeader; readBytes( fileHeader.magic, sizeof(fileHeader.magic) ); read( fileHeader.versionMajor ); read( fileHeader.versionMinor ); read( fileHeader.modelFlags ); read( fileHeader.offsetCount ); if ( strncmp( fileHeader.magic, MAGIC, strlen(MAGIC) ) != 0 ) { delete[] fileBuf; log_warning( "bad magic number file\n" ); return Model::ERROR_BAD_MAGIC; } if ( fileHeader.versionMajor != WRITE_VERSION_MAJOR ) { delete[] fileBuf; return Model::ERROR_UNSUPPORTED_VERSION; } unsigned offsetCount = fileHeader.offsetCount; log_debug( "Misfit file:\n" ); log_debug( " major: %d\n", fileHeader.versionMajor ); log_debug( " minor: %d\n", fileHeader.versionMinor ); log_debug( " offsets: %d\n", fileHeader.offsetCount ); log_debug( "Offset information:\n" ); unsigned t; MisfitOffsetList offsetList; unsigned lastOffset = 0; bool lastUnknown = false; UnknownDataList unknownList; for ( t = 0; t < offsetCount; t++ ) { MisfitOffsetT mo; read( mo.offsetType ); read( mo.offsetValue ); if ( mo.offsetValue < lastOffset ) { log_error( "Offset are out of order\n" ); delete[] fileBuf; return Model::ERROR_BAD_DATA; } if ( lastUnknown ) { unknownList.back().dataLen = mo.offsetValue - lastOffset; log_warning( "unknown data size = %d\n", unknownList.back().dataLen ); lastUnknown = false; } lastOffset = mo.offsetValue; offsetList.push_back( mo ); bool found = false; for ( unsigned e = 0; !found && e < MDT_MAX; e++ ) { if ( _misfitOffsetTypes[e] == (mo.offsetType & OFFSET_TYPE_MASK) ) { log_debug( " %08X %s\n", mo.offsetValue, _misfitOffsetNames[e] ); found = true; if ( e == MDT_EndOfFile ) { if ( mo.offsetValue != fileLength ) { if ( mo.offsetValue > fileLength ) { return Model::ERROR_UNEXPECTED_EOF; } else { log_warning( "EOF offset and file size do not match (%d and %d)\n", mo.offsetValue, fileLength ); return Model::ERROR_BAD_DATA; } } } } } if ( !found ) { log_debug( " %08X Unknown type %04X\n", mo.offsetValue, mo.offsetType ); lastUnknown = true; UnknownDataT ud; ud.offsetType = mo.offsetType; ud.offsetValue = mo.offsetValue; ud.dataLen = 0; unknownList.push_back( ud ); } } vector & modelVertices = getVertexList( model ); vector & modelTriangles = getTriangleList( model ); vector & modelGroups = getGroupList( model ); vector & modelMaterials = getMaterialList( model ); vector & modelJoints = getJointList( model ); // Used to track whether indices are valid bool missingElements = false; // Meta data if ( _offsetIncluded( MDT_Meta, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Meta, offsetList ); uint32_t offset = _offsetGet( MDT_Meta, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned m = 0; m < count; m++ ) { if ( variable ) { read( size ); } unsigned len; char key[1024]; char value[1024]; strncpy( key, (char *) m_bufPos, sizeof(key) ); utf8chrtrunc( key, sizeof(key)-1 ); len = strlen(key) + 1; m_bufPos += len; m_readLength -= len; strncpy( value, (char *) m_bufPos, sizeof(value) ); utf8chrtrunc( value, sizeof(value)-1 ); len = strlen(value) + 1; m_bufPos += len; m_readLength -= len; model->addMetaData( key, value ); } } // Vertices if ( _offsetIncluded( MDT_Vertices, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Vertices, offsetList ); uint32_t offset = _offsetGet( MDT_Vertices, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned v = 0; v < count; v++ ) { if ( variable ) { read( size ); } MM3DFILE_VertexT fileVert; read( fileVert.flags ); read( fileVert.coord[0] ); read( fileVert.coord[1] ); read( fileVert.coord[2] ); Model::Vertex * vert = Model::Vertex::get(); //vert->m_boneId = -1; vert->m_coord[0] = fileVert.coord[0]; vert->m_coord[1] = fileVert.coord[1]; vert->m_coord[2] = fileVert.coord[2]; uint16_t vertFlags = fileVert.flags; vert->m_selected = ((vertFlags & MF_SELECTED) == MF_SELECTED); vert->m_visible = ((vertFlags & MF_HIDDEN) != MF_HIDDEN); vert->m_free = ((vertFlags & MF_VERTFREE) == MF_VERTFREE); modelVertices.push_back( vert ); } } // Triangles if ( _offsetIncluded( MDT_Triangles, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Triangles, offsetList ); uint32_t offset = _offsetGet( MDT_Triangles, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { read( size ); } MM3DFILE_TriangleT fileTri; read( fileTri.flags ); read( fileTri.vertex[0] ); read( fileTri.vertex[1] ); read( fileTri.vertex[2] ); Model::Triangle * tri = Model::Triangle::get(); tri->m_vertexIndices[0] = fileTri.vertex[0]; tri->m_vertexIndices[1] = fileTri.vertex[1]; tri->m_vertexIndices[2] = fileTri.vertex[2]; uint16_t triFlags = fileTri.flags; tri->m_selected = ((triFlags & MF_SELECTED) == MF_SELECTED); tri->m_visible = ((triFlags & MF_HIDDEN) != MF_HIDDEN); tri->m_projection = -1; modelTriangles.push_back( tri ); } } #if 0 // Triangle Normals if ( _offsetIncluded( MDT_TriangleNormals, offsetList ) ) { // Just for debugging... we don't actually use any of this bool variable = _offsetIsVariable( MDT_TriangleNormals, offsetList ); uint32_t offset = _offsetGet( MDT_TriangleNormals, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { read( size ); } MM3DFILE_TriangleNormalsT fileTri; read( fileTri.flags ); read( fileTri.index ); read( fileTri.normal[0][0] ); read( fileTri.normal[0][1] ); read( fileTri.normal[0][2] ); read( fileTri.normal[1][0] ); read( fileTri.normal[1][1] ); read( fileTri.normal[1][2] ); read( fileTri.normal[2][0] ); read( fileTri.normal[2][1] ); read( fileTri.normal[2][2] ); log_debug( "triangle %d normals:\n", fileTri.index ); for ( unsigned v = 0; v < 3; v++ ) { log_debug( " v %d: %f %f %f\n", v, fileTri.normal[v][0], fileTri.normal[v][1], fileTri.normal[v][2] ); } } } #endif // 0 // Groups if ( _offsetIncluded( MDT_Groups, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Groups, offsetList ); uint32_t offset = _offsetGet( MDT_Groups, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned g = 0; g < count; g++ ) { if ( variable ) { read( size ); } Model::Group * grp = Model::Group::get(); uint16_t flags; uint32_t triCount; uint8_t smoothness; uint32_t materialIndex; char name[1024]; read( flags ); strncpy( name, (char *) m_bufPos, sizeof(name)); utf8chrtrunc( name, sizeof(name)-1 ); unsigned nameSize = strlen(name) + 1; m_bufPos += nameSize; m_readLength -= nameSize; read( triCount ); for ( unsigned t = 0; t < triCount; t++ ) { uint32_t triIndex = 0; read( triIndex ); grp->m_triangleIndices.insert( triIndex ); } read( smoothness ); read( materialIndex ); grp->m_name = name; grp->m_smooth = smoothness; grp->m_selected = ((flags & MF_SELECTED) == MF_SELECTED); grp->m_visible = ((flags & MF_HIDDEN) != MF_HIDDEN); grp->m_materialIndex = materialIndex; modelGroups.push_back( grp ); } } // External Textures std::vector< std::string > texNames; if ( _offsetIncluded( MDT_ExtTextures, offsetList ) ) { bool variable = _offsetIsVariable( MDT_ExtTextures, offsetList ); uint32_t offset = _offsetGet( MDT_ExtTextures, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned t = 0; t < count; t++ ) { log_debug( "reading external texture %d/%d\n", t, count ); if ( variable ) { read( size ); } uint16_t flags; char filename[PATH_MAX]; read( flags ); strncpy( filename, (char *) m_bufPos, sizeof(filename)); utf8chrtrunc( filename, sizeof(filename)-1 ); unsigned nameSize = strlen(filename) + 1; m_bufPos += nameSize; m_readLength -= nameSize; replaceBackslash( filename ); log_debug( " filename is %s\n", filename ); std::string fullpath = getAbsolutePath( modelPath.c_str(), filename ); texNames.push_back( fullpath ); } } // Materials if ( _offsetIncluded( MDT_Materials, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Materials, offsetList ); uint32_t offset = _offsetGet( MDT_Materials, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned m = 0; m < count; m++ ) { log_debug( "reading material %d/%d\n", m, count ); if ( variable ) { read( size ); } uint16_t flags = 0; uint32_t texIndex = 0; char name[1024]; Model::Material * mat = Model::Material::get(); read( flags ); read( texIndex ); strncpy( name, (char *) m_bufPos, sizeof(name)); utf8chrtrunc( name, sizeof(name)-1 ); unsigned nameSize = strlen(name) + 1; m_bufPos += nameSize; m_readLength -= nameSize; log_debug( " material name: %s\n", name ); mat->m_name = name; switch ( flags & 0x0f ) { case 0: log_debug( " got external texture %d\n", texIndex ); mat->m_type = Model::Material::MATTYPE_TEXTURE; if ( texIndex < texNames.size() ) { mat->m_filename = texNames[texIndex]; } else { mat->m_filename = ""; } break; case 13: mat->m_type = Model::Material::MATTYPE_COLOR; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; case 14: mat->m_type = Model::Material::MATTYPE_GRADIENT; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; case 15: mat->m_type = Model::Material::MATTYPE_BLANK; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; default: log_debug( " got unknown material type\n", texIndex ); mat->m_type = Model::Material::MATTYPE_BLANK; mat->m_filename = ""; memset( mat->m_color, 255, sizeof( mat->m_color ) ); break; } mat->m_sClamp = ( (flags & MF_MAT_CLAMP_S) != 0 ); mat->m_tClamp = ( (flags & MF_MAT_CLAMP_T) != 0 ); unsigned i = 0; float32_t lightProp = 0; for ( i = 0; i < 4; i++ ) { read( lightProp ); mat->m_ambient[i] = lightProp; } for ( i = 0; i < 4; i++ ) { read( lightProp ); mat->m_diffuse[i] = lightProp; } for ( i = 0; i < 4; i++ ) { read( lightProp ); mat->m_specular[i] = lightProp; } for ( i = 0; i < 4; i++ ) { read( lightProp ); mat->m_emissive[i] = lightProp; } read( lightProp ); mat->m_shininess = lightProp; modelMaterials.push_back( mat ); } } // Texture coordinates if ( _offsetIncluded( MDT_TexCoords, offsetList ) ) { bool variable = _offsetIsVariable( MDT_TexCoords, offsetList ); uint32_t offset = _offsetGet( MDT_TexCoords, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned c = 0; c < count; c++ ) { if ( variable ) { read( size ); } MM3DFILE_TexCoordT tc; read( tc.flags ); read( tc.triangleIndex ); read( tc.sCoord[0] ); read( tc.sCoord[1] ); read( tc.sCoord[2] ); read( tc.tCoord[0] ); read( tc.tCoord[1] ); read( tc.tCoord[2] ); uint32_t triIndex = tc.triangleIndex; if ( triIndex < modelTriangles.size() ) { for ( unsigned v = 0; v < 3; v++ ) { modelTriangles[triIndex]->m_s[v] = tc.sCoord[v]; modelTriangles[triIndex]->m_t[v] = tc.tCoord[v]; } } } } // Canvas Background Images if ( _offsetIncluded( MDT_CanvasBackgrounds, offsetList ) ) { bool variable = _offsetIsVariable( MDT_CanvasBackgrounds, offsetList ); uint32_t offset = _offsetGet( MDT_CanvasBackgrounds, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned g = 0; g < count; g++ ) { log_debug( "reading canvas background %d/%d\n", g, count ); if ( variable ) { read( size ); } MM3DFILE_CanvasBackgroundT cb; read( cb.flags ); read( cb.viewIndex ); read( cb.scale ); read( cb.center[0] ); read( cb.center[1] ); read( cb.center[2] ); char name[PATH_MAX]; strncpy( name, (char *) m_bufPos, sizeof(name)); utf8chrtrunc( name, sizeof(name)-1 ); unsigned nameSize = strlen(name) + 1; m_bufPos += nameSize; m_readLength -= nameSize; replaceBackslash( name ); std::string fileStr = getAbsolutePath( modelPath.c_str(), name ); model->setBackgroundImage( cb.viewIndex, fileStr.c_str() ); model->setBackgroundScale( cb.viewIndex, cb.scale ); model->setBackgroundCenter( cb.viewIndex, cb.center[0], cb.center[1], cb.center[2] ); } } // Joints if ( _offsetIncluded( MDT_Joints, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Joints, offsetList ); uint32_t offset = _offsetGet( MDT_Joints, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned j = 0; j < count; j++ ) { log_debug( "reading joint %d/%d\n", j, count ); if ( variable ) { read( size ); } MM3DFILE_JointT fileJoint; read( fileJoint.flags ); readBytes( fileJoint.name, sizeof(fileJoint.name) ); read( fileJoint.parentIndex ); read( fileJoint.localRot[0] ); read( fileJoint.localRot[1] ); read( fileJoint.localRot[2] ); read( fileJoint.localTrans[0] ); read( fileJoint.localTrans[1] ); read( fileJoint.localTrans[2] ); Model::Joint * joint = Model::Joint::get(); fileJoint.name[ sizeof(fileJoint.name) - 1 ] = '\0'; joint->m_name = fileJoint.name; joint->m_parent = fileJoint.parentIndex; for ( unsigned i = 0; i < 3; i++ ) { joint->m_localRotation[i] = fileJoint.localRot[i]; joint->m_localTranslation[i] = fileJoint.localTrans[i]; } uint16_t jointFlags = fileJoint.flags; joint->m_selected = ((jointFlags & MF_SELECTED) == MF_SELECTED); joint->m_visible = ((jointFlags & MF_HIDDEN) != MF_HIDDEN); modelJoints.push_back( joint ); } log_debug( "read %d joints\n", count ); } // Joint Vertices // Newer versions of the file format use MDT_WeightedInfluences instead. // We still want to read this data to use as a default in case the // weighted influences are not present. if ( _offsetIncluded( MDT_JointVertices, offsetList ) ) { bool variable = _offsetIsVariable( MDT_JointVertices, offsetList ); uint32_t offset = _offsetGet( MDT_JointVertices, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { read( size ); } uint32_t vertexIndex = 0; int32_t jointIndex = 0; read( vertexIndex ); read( jointIndex ); if ( vertexIndex < modelVertices.size() && (unsigned) jointIndex < modelJoints.size() ) { //modelVertices[ vertexIndex ]->m_boneId = jointIndex; model->addVertexInfluence( vertexIndex, jointIndex, Model::IT_Custom, 1.0 ); } else { missingElements = true; log_error( "vertex %d or joint %d out of range\n", vertexIndex, jointIndex ); } } log_debug( "read %d joints vertices\n", count ); } // Points if ( _offsetIncluded( MDT_Points, offsetList ) ) { bool variable = _offsetIsVariable( MDT_Points, offsetList ); uint32_t offset = _offsetGet( MDT_Points, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned j = 0; j < count; j++ ) { log_debug( "reading Point %d/%d\n", j, count ); if ( variable ) { read( size ); } MM3DFILE_PointT filePoint; read( filePoint.flags ); readBytes( filePoint.name, sizeof(filePoint.name) ); read( filePoint.type ); read( filePoint.boneIndex ); read( filePoint.rot[0] ); read( filePoint.rot[1] ); read( filePoint.rot[2] ); read( filePoint.trans[0] ); read( filePoint.trans[1] ); read( filePoint.trans[2] ); filePoint.name[ sizeof(filePoint.name) - 1 ] = '\0'; float rot[3]; float trans[3]; for ( unsigned i = 0; i < 3; i++ ) { rot[i] = filePoint.rot[i]; trans[i] = filePoint.trans[i]; } int boneIndex = filePoint.boneIndex; int p = model->addPoint( filePoint.name, trans[0], trans[1], trans[2], rot[0], rot[1], rot[2], boneIndex ); int type = filePoint.type; model->setPointType( p, type ); uint16_t pointFlags = filePoint.flags; if ( (pointFlags & MF_SELECTED) == MF_SELECTED ) { model->selectPoint( p ); } if ( (pointFlags & MF_HIDDEN) == MF_HIDDEN) { model->hidePoint( p ); } } log_debug( "read %d points\n" ); } // Smooth Angles if ( _offsetIncluded( MDT_SmoothAngles, offsetList ) ) { bool variable = _offsetIsVariable( MDT_SmoothAngles, offsetList ); uint32_t offset = _offsetGet( MDT_SmoothAngles, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { read( size ); } MM3DFILE_SmoothAngleT fileSa; read( fileSa.groupIndex ); read( fileSa.angle ); if ( fileSa.angle > 180 ) { fileSa.angle = 180; } if ( fileSa.groupIndex < modelGroups.size() ) { model->setGroupAngle( fileSa.groupIndex, fileSa.angle ); } } log_debug( "read %d group smoothness angles\n", count ); } // Weighted influences if ( _offsetIncluded( MDT_WeightedInfluences, offsetList ) ) { bool variable = _offsetIsVariable( MDT_WeightedInfluences, offsetList ); uint32_t offset = _offsetGet( MDT_WeightedInfluences, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } unsigned vcount = model->getVertexCount(); for ( unsigned v = 0; v < vcount; v++ ) { model->removeAllVertexInfluences( v ); } unsigned pcount = model->getVertexCount(); for ( unsigned p = 0; p < pcount; p++ ) { model->removeAllPointInfluences( p ); } for ( unsigned t = 0; t < count; t++ ) { if ( variable ) { read( size ); } MM3DFILE_WeightedInfluenceT fileWi; read( fileWi.posType ); read( fileWi.posIndex ); read( fileWi.infIndex ); read( fileWi.infType ); read( fileWi.infWeight ); if ( fileWi.posType == Model::PT_Vertex || fileWi.posType == Model::PT_Point ) { Model::Position pos; pos.type = static_cast( fileWi.posType ); pos.index = fileWi.posIndex; Model::InfluenceTypeE type = Model::IT_Custom; switch ( fileWi.infType ) { case Model::IT_Custom: case Model::IT_Auto: case Model::IT_Remainder: type = static_cast( fileWi.infType ); break; default: log_error( "unknown influence type %d\n", fileWi.infType ); break; } double weight = ((double) fileWi.infWeight) / 100.0; log_debug( "adding position influence %d,%d,%f\n", pos.index, (int) type, (float) weight ); model->addPositionInfluence( pos, fileWi.infIndex, type, weight ); } } } // Texture Projections if ( _offsetIncluded( MDT_TexProjections, offsetList ) ) { bool variable = _offsetIsVariable( MDT_TexProjections, offsetList ); uint32_t offset = _offsetGet( MDT_TexProjections, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned j = 0; j < count; j++ ) { log_debug( "reading Projection %d/%d\n", j, count ); if ( variable ) { read( size ); } uint16_t flags = 0; read( flags ); std::string name; name.assign( (char *) m_bufPos, 40 ); m_bufPos += 40; m_readLength -= 40; int32_t type = 0; read( type ); double vec[3]; float fvec[3]; unsigned i = 0; // position for ( unsigned i = 0; i < 3; i++ ) { read( fvec[i] ); vec[i] = fvec[i]; } int proj = model->addProjection( name.c_str(), type, vec[0], vec[1], vec[2] ); // up vector for ( unsigned i = 0; i < 3; i++ ) { read( fvec[i] ); vec[i] = fvec[i]; } model->setProjectionUp( proj, vec ); // seam vector for ( unsigned i = 0; i < 3; i++ ) { read( fvec[i] ); vec[i] = fvec[i]; } model->setProjectionSeam( proj, vec ); double uv[2][2]; float fuv[2][2]; // texture coordinate range for ( i = 0; i < 2; i++ ) { for ( int j = 0; j < 2; j++ ) { read( fuv[i][j] ); uv[i][j] = fuv[i][j]; } } model->setProjectionRange( proj, uv[0][0], uv[0][1], uv[1][0], uv[1][1] ); } log_debug( "read %d projections\n" ); } // Texture Projection Triangles (have to read this after projections) if ( _offsetIncluded( MDT_ProjectionTriangles, offsetList ) ) { bool variable = _offsetIsVariable( MDT_ProjectionTriangles, offsetList ); uint32_t offset = _offsetGet( MDT_ProjectionTriangles, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned c = 0; c < count; c++ ) { if ( variable ) { read( size ); } uint32_t proj = 0; uint32_t triCount = 0; uint32_t tri = 0; read( proj ); read( triCount ); uint32_t t; for ( t = 0; t < triCount; t++ ) { read( tri ); model->setTriangleProjection( tri, proj ); } } } // Skeletal Animations if ( _offsetIncluded( MDT_SkelAnims, offsetList ) ) { bool variable = _offsetIsVariable( MDT_SkelAnims, offsetList ); uint32_t offset = _offsetGet( MDT_SkelAnims, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned s = 0; s < count; s++ ) { log_debug( "reading skel anim %d/%d\n", s, count ); if ( variable ) { read( size ); } uint16_t flags; char name[1024]; float32_t fps; uint32_t frameCount; read( flags ); strncpy( name, (char *) m_bufPos, sizeof(name)); utf8chrtrunc( name, sizeof(name)-1 ); unsigned nameSize = strlen(name) + 1; m_bufPos += nameSize; m_readLength -= nameSize; log_debug( " name is %s\n", name ); read( fps ); read( frameCount ); unsigned anim = model->addAnimation( Model::ANIMMODE_SKELETAL, name ); model->setAnimFPS( Model::ANIMMODE_SKELETAL, anim, fps ); model->setAnimFrameCount( Model::ANIMMODE_SKELETAL, anim, frameCount ); for ( unsigned f = 0; f < frameCount; f++ ) { uint32_t keyframeCount; read( keyframeCount ); for ( unsigned k = 0; k < keyframeCount; k++ ) { MM3DFILE_SkelKeyframeT fileKf; read( fileKf.jointIndex ); read( fileKf.keyframeType ); read( fileKf.param[0] ); read( fileKf.param[1] ); read( fileKf.param[2] ); model->setSkelAnimKeyframe( anim, f, fileKf.jointIndex, (fileKf.keyframeType ? false : true), fileKf.param[0], fileKf.param[1], fileKf.param[2] ); } } } } // Frame Animations if ( _offsetIncluded( MDT_FrameAnims, offsetList ) ) { bool variable = _offsetIsVariable( MDT_FrameAnims, offsetList ); uint32_t offset = _offsetGet( MDT_FrameAnims, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned a = 0; a < count; a++ ) { log_debug( "reading frame animation %d/%d\n", a, count ); if ( variable ) { read( size ); } if ( size > m_readLength ) { log_error( "Size of frame animation is too large for file data\n" ); delete[] fileBuf; return Model::ERROR_BAD_DATA; } uint16_t flags; char name[1024]; float32_t fps; uint32_t frameCount; read( flags ); strncpy( name, (char *) m_bufPos, sizeof(name)); utf8chrtrunc( name, sizeof(name)-1 ); log_debug( "anim name '%s' size %d\n", name, size ); unsigned nameSize = strlen(name) + 1; m_bufPos += nameSize; m_readLength -= nameSize; read( fps ); log_debug( "fps %f\n", fps ); read( frameCount ); log_debug( "frame count %u\n", frameCount ); if ( (frameCount > size) || ((frameCount * modelVertices.size() * sizeof(float32_t)) * 3 > (size - 10))) { log_error( "Frame count for animation is too large for file data\n" ); delete[] fileBuf; return Model::ERROR_BAD_DATA; } unsigned anim = model->addAnimation( Model::ANIMMODE_FRAME, name ); model->setAnimFPS( Model::ANIMMODE_FRAME, anim, fps ); model->setAnimFrameCount( Model::ANIMMODE_FRAME, anim, frameCount ); for ( unsigned f = 0; f < frameCount; f++ ) { unsigned maxVertex = 0; float32_t coord[3]; for ( unsigned v = 0; v < modelVertices.size(); v++ ) { for ( unsigned i = 0; i < 3; i++ ) { read( coord[i] ); } model->setFrameAnimVertexCoords( anim, f, v, coord[0], coord[1], coord[2] ); maxVertex = v; } maxVertex = maxVertex + 1; if ( (maxVertex) != modelVertices.size() ) { missingElements = true; log_error( "Vertex count for frame animation %d, frame %d has %d vertices, should be %d\n", anim, f, maxVertex, modelVertices.size() ); } } } } // Frame Animation Points if ( _offsetIncluded( MDT_FrameAnimPoints, offsetList ) ) { bool variable = _offsetIsVariable( MDT_FrameAnimPoints, offsetList ); uint32_t offset = _offsetGet( MDT_FrameAnimPoints, offsetList ); m_bufPos = &fileBuf[offset]; m_readLength = fileLength - offset; uint16_t flags = 0; uint32_t count = 0; read( flags ); read( count ); uint32_t size = 0; if ( !variable ) { read( size ); } for ( unsigned a = 0; a < count; a++ ) { if ( variable ) { read( size ); } uint16_t flags; uint32_t anim; uint32_t frameCount; read( flags ); read( anim ); read( frameCount ); size_t pcount = model->getPointCount(); for ( unsigned f = 0; f < frameCount; f++ ) { float32_t rot[3]; float32_t trans[3]; for ( unsigned p = 0; p < pcount; p++ ) { for ( unsigned i = 0; i < 3; i++ ) { read( rot[i] ); } for ( unsigned i = 0; i < 3; i++ ) { read( trans[i] ); } model->setFrameAnimPointCoords( anim, f, p, trans[0], trans[1], trans[2] ); model->setFrameAnimPointRotation( anim, f, p, rot[0], rot[1], rot[2] ); } } } } // Read unknown data UnknownDataList::iterator it; for ( it = unknownList.begin(); it != unknownList.end(); it++ ) { Model::FormatData * fd = new Model::FormatData; fd->offsetType = (*it).offsetType; m_bufPos = &fileBuf[ (*it).offsetValue ]; log_debug( "unknown data is type %x...\n", fd->offsetType ); fd->data = new uint8_t[ (*it).dataLen ]; fd->len = (*it).dataLen; memcpy( fd->data, m_bufPos, (*it).dataLen ); if ( model->addFormatData( fd ) < 0 ) { delete fd; } } // Account for missing elements (vertices, triangles, textures, joints) { unsigned vcount = modelVertices.size(); unsigned tcount = modelTriangles.size(); unsigned gcount = modelGroups.size(); unsigned jcount = modelJoints.size(); unsigned mcount = modelMaterials.size(); // for ( unsigned v = 0; v < vcount; v++ ) // { // if ( modelVertices[v]->m_boneId >= (signed) jcount ) // { // missingElements = true; // log_error( "Vertex %d uses missing bone joint %d\n", v, modelVertices[v]->m_boneId ); // } // } for ( unsigned t = 0; t < tcount; t++ ) { for ( unsigned i = 0; i < 3; i++ ) { if ( modelTriangles[t]->m_vertexIndices[i] >= vcount ) { missingElements = true; log_error( "Triangle %d uses missing vertex %d\n", t, modelTriangles[t]->m_vertexIndices[i] ); } } } for ( unsigned g = 0; g < gcount; g++ ) { for ( std::set::const_iterator it = modelGroups[g]->m_triangleIndices.begin(); it != modelGroups[g]->m_triangleIndices.end(); ++it ) { if ( *it >= (signed) tcount ) { missingElements = true; log_error( "Group %d uses missing triangle %d\n", g, *it ); } } if ( modelGroups[g]->m_materialIndex >= (signed) mcount ) { missingElements = true; log_error( "Group %d uses missing texture %d\n", g, modelGroups[g]->m_materialIndex ); } } for ( unsigned j = 0; j < jcount; j++ ) { if ( modelJoints[j]->m_parent >= (signed) jcount ) { log_warning( "Joint %d has bad parent joint, checking endianness\n", j ); if ( htonl( modelJoints[j]->m_parent ) < jcount ) { modelJoints[j]->m_parent = htonl( modelJoints[j]->m_parent ); } else if ( htol_u32( modelJoints[j]->m_parent ) < jcount ) { modelJoints[j]->m_parent = htol_u32( modelJoints[j]->m_parent ); } else { missingElements = true; log_error( "Joint %d has missing parent joint %d\n", j, modelJoints[j]->m_parent ); } } } } delete[] fileBuf; if ( missingElements ) { log_warning( "missing elements in file\n" ); return Model::ERROR_BAD_DATA; } else { model->setupJoints(); return Model::ERROR_NONE; } } Model::ModelErrorE MisfitFilterRef::writeFile( Model * model, const char * const filename, ModelFilter::Options * o ) { return Model::ERROR_UNSUPPORTED_OPERATION; } bool MisfitFilterRef::canRead( const char * filename ) { return true; } bool MisfitFilterRef::canWrite( const char * filename ) { return true; } bool MisfitFilterRef::canExport( const char * filename ) { return true; } bool MisfitFilterRef::isSupported( const char * filename ) { unsigned len = strlen( filename ); if ( len >= 5 && strcasecmp( &filename[len-5], ".mm3d" ) == 0 ) { return true; } else { return false; } } list< string > MisfitFilterRef::getReadTypes() { list rval; rval.push_back( "*.mm3d" ); return rval; } list< string > MisfitFilterRef::getWriteTypes() { list rval; rval.push_back( "*.mm3d" ); return rval; } void MisfitFilterRef::write( uint32_t val ) { val = htol_u32( val ); fwrite( &val, sizeof(val), 1, m_fp ); } void MisfitFilterRef::write( uint16_t val ) { val = htol_u16( val ); fwrite( &val, sizeof(val), 1, m_fp ); } void MisfitFilterRef::write( uint8_t val ) { fwrite( &val, sizeof(val), 1, m_fp ); } void MisfitFilterRef::write( int32_t val ) { val = htol_32( val ); fwrite( &val, sizeof(val), 1, m_fp ); } void MisfitFilterRef::write( int16_t val ) { val = htol_16( val ); fwrite( &val, sizeof(val), 1, m_fp ); } void MisfitFilterRef::write( int8_t val ) { fwrite( &val, sizeof(val), 1, m_fp ); } void MisfitFilterRef::write( float32_t val ) { val = htol_float( val ); fwrite( &val, sizeof(val), 1, m_fp ); } void MisfitFilterRef::writeBytes( const void * buf, size_t len ) { fwrite( buf, len, 1, m_fp ); } void MisfitFilterRef::writeHeaderA( uint16_t flags, uint32_t count ) { write( flags ); write( count ); } void MisfitFilterRef::writeHeaderB( uint16_t flags, uint32_t count, uint32_t size ) { write( flags ); write( count ); write( size ); } void MisfitFilterRef::read( uint32_t & val ) { if ( m_readLength >= sizeof( val ) ) { val = ltoh_u32( * (uint32_t*) m_bufPos ); m_bufPos += sizeof( uint32_t ); m_readLength -= sizeof( uint32_t ); } } void MisfitFilterRef::read( uint16_t & val ) { if ( m_readLength >= sizeof( val ) ) { val = ltoh_u16( * (uint16_t*) m_bufPos ); m_bufPos += sizeof( uint16_t ); m_readLength -= sizeof( uint16_t ); } } void MisfitFilterRef::read( uint8_t & val ) { if ( m_readLength >= sizeof( val ) ) { val = * (uint8_t*) m_bufPos; m_bufPos += sizeof( uint8_t ); m_readLength -= sizeof( uint8_t ); } } void MisfitFilterRef::read( int32_t & val ) { if ( m_readLength >= sizeof( val ) ) { val = ltoh_32( * (int32_t*) m_bufPos ); m_bufPos += sizeof( int32_t ); m_readLength -= sizeof( int32_t ); } } void MisfitFilterRef::read( int16_t & val ) { if ( m_readLength >= sizeof( val ) ) { val = ltoh_16( * (int16_t*) m_bufPos ); m_bufPos += sizeof( int16_t ); m_readLength -= sizeof( int16_t ); } } void MisfitFilterRef::read( int8_t & val ) { if ( m_readLength >= sizeof( val ) ) { val = * (int8_t*) m_bufPos; m_bufPos += sizeof( int8_t ); m_readLength -= sizeof( int8_t ); } } void MisfitFilterRef::read( float32_t & val ) { if ( m_readLength >= sizeof( val ) ) { val = ltoh_float( * (float32_t*) m_bufPos ); m_bufPos += sizeof( float32_t ); m_readLength -= sizeof( float32_t ); } } void MisfitFilterRef::readBytes( void * buf, size_t len ) { if ( m_readLength >= len ) { memcpy( buf, m_bufPos, len ); m_bufPos += len; m_readLength -= len; } } void MisfitFilterRef::readHeaderA( uint16_t & flags, uint32_t & count ) { read( flags ); read( count ); } void MisfitFilterRef::readHeaderB( uint16_t & flags, uint32_t & count, uint32_t & size ) { read( flags ); read( count ); read( size ); } //----------------------------------------------------------------------------- // End reference code //----------------------------------------------------------------------------- mm3d-1.3.7/src/libmm3d/pcxtex.h0000644000175000017500000000454410744511346013121 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __PCXTEX_H #define __PCXTEX_H #include "texmgr.h" #include class PcxTextureFilter : public TextureFilter { public: PcxTextureFilter(); virtual ~PcxTextureFilter(); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); Texture::ErrorE readFile( Texture * texture, const char * filename ); bool canRead( const char * filename ); protected: Texture::ErrorE load_image ( const char *filename ); void load_1 (FILE *fp, int width, int height, uint8_t *buffer, int bytes); void load_4 (FILE *fp, int width, int height, uint8_t *buffer, int bytes); void load_8 (FILE *fp, int width, int height, uint8_t *buffer, int bytes); void load_24 (FILE *fp, int width, int height, uint8_t *buffer, int bytes); void readline (FILE *fp, uint8_t *buffer, int bytes); void read( uint8_t & val, FILE * fp ); void read( int16_t & val, FILE * fp ); void readBytes( void * buf, size_t len, FILE * fp ); /* bool save_image (char *filename, int32_t image, int32_t layer); void save_8 (FILE *fp, int width, int height, unsigned char *buffer); void save_24 (FILE *fp, int width, int height, unsigned char *buffer); void writeline (FILE *fp, unsigned char *buffer, int bytes); */ uint8_t m_palette[256][3]; Texture * m_texture; }; #endif // __PCXTEX_H mm3d-1.3.7/src/libmm3d/model_group.cc0000644000175000017500000002136410746733504014263 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "log.h" #ifdef MM3D_EDIT #include "modelundo.h" #endif // MM3D_EDIT #ifdef MM3D_EDIT int Model::addGroup( const char * name ) { LOG_PROFILE(); if ( m_animationMode ) { return -1; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return -1; } m_changeBits |= AddOther; if ( name ) { int num = m_groups.size(); Group * group = Group::get(); group->m_name = name; m_groups.push_back( group ); MU_AddGroup * undo = new MU_AddGroup(); undo->addGroup( num, group ); sendUndo( undo ); return num; } else { return -1; } } void Model::deleteGroup( unsigned groupNum ) { LOG_PROFILE(); if ( m_animationMode ) { return; } if ( m_frameAnims.size() > 0 && !m_forceAddOrDelete) { displayFrameAnimPrimitiveError(); return; } MU_DeleteGroup * undo = new MU_DeleteGroup(); undo->deleteGroup( groupNum, m_groups[ groupNum ] ); sendUndo( undo ); removeGroup( groupNum ); } bool Model::setGroupSmooth( unsigned groupNum, uint8_t smooth ) { if ( m_animationMode ) { return false; } if ( groupNum < m_groups.size() ) { MU_SetGroupSmooth * undo = new MU_SetGroupSmooth(); undo->setGroupSmooth( groupNum, smooth, m_groups[groupNum]->m_smooth ); sendUndo( undo ); m_groups[ groupNum ]->m_smooth = smooth; m_validNormals = false; return true; } else { return false; } } bool Model::setGroupAngle( unsigned groupNum, uint8_t angle ) { if ( m_animationMode ) { return false; } if ( groupNum < m_groups.size() ) { MU_SetGroupAngle * undo = new MU_SetGroupAngle(); undo->setGroupAngle( groupNum, angle, m_groups[groupNum]->m_angle ); sendUndo( undo ); m_groups[ groupNum ]->m_angle = angle; m_validNormals = false; return true; } else { return false; } } bool Model::setGroupName( unsigned groupNum, const char * name ) { if ( m_animationMode ) { return false; } if ( groupNum >= 0 && groupNum < m_groups.size() && name ) { MU_SetGroupName * undo = new MU_SetGroupName(); undo->setGroupName( groupNum, name, m_groups[groupNum]->m_name.c_str() ); sendUndo( undo ); m_groups[ groupNum ]->m_name = name; return true; } else { return false; } } void Model::setSelectedAsGroup( unsigned groupNum ) { LOG_PROFILE(); if ( m_animationMode ) { return; } m_changeBits |= AddOther; invalidateNormals(); m_validBspTree = false; if ( groupNum < m_groups.size() ) { Group * grp = m_groups[groupNum]; unsigned t = 0; while ( !grp->m_triangleIndices.empty() ) { removeTriangleFromGroup( groupNum, *grp->m_triangleIndices.begin() ); } // Put selected triangles into group groupNum for ( t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_selected ) { addTriangleToGroup( groupNum, t ); } } // Remove selected triangles from other groups for ( t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_selected ) { for ( unsigned g = 0; g < m_groups.size(); g++ ) { if ( g != groupNum ) { removeTriangleFromGroup( g, t ); } } } } } } void Model::addSelectedToGroup( unsigned groupNum ) { LOG_PROFILE(); if ( m_animationMode ) { return; } m_changeBits |= AddOther; invalidateNormals(); m_validBspTree = false; if ( groupNum < m_groups.size() ) { for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_selected ) { int g = getTriangleGroup( t ); if ( g != (int) groupNum ) { if ( g >= 0 ) removeTriangleFromGroup( g, t ); addTriangleToGroup( groupNum, t ); } } } } } void Model::addTriangleToGroup( unsigned groupNum, unsigned triangleNum ) { LOG_PROFILE(); if ( m_animationMode ) { return; } m_changeBits |= AddOther; if ( groupNum < m_groups.size() && triangleNum < m_triangles.size() ) { m_validBspTree = false; m_groups[groupNum]->m_triangleIndices.insert( triangleNum ); MU_AddToGroup * undo = new MU_AddToGroup(); undo->addToGroup( groupNum, triangleNum ); sendUndo( undo ); } else { log_error( "addTriangleToGroup(%d, %d) argument out of range\n", groupNum, triangleNum ); } } void Model::removeTriangleFromGroup( unsigned groupNum, unsigned triangleNum ) { if ( m_animationMode ) { return; } m_validBspTree = false; if ( groupNum < m_groups.size() && triangleNum < m_triangles.size() ) { Group * grp = m_groups[ groupNum ]; std::set::iterator it = grp->m_triangleIndices.find( triangleNum ); if ( it != grp->m_triangleIndices.end() ) { grp->m_triangleIndices.erase( it ); MU_RemoveFromGroup * undo = new MU_RemoveFromGroup(); undo->removeFromGroup( groupNum, triangleNum ); sendUndo( undo ); } } else { log_error( "addTriangleToGroup(%d, %d) argument out of range\n", groupNum, triangleNum ); } } #endif // MM3D_EDIT list Model::getUngroupedTriangles() const { list triangles; unsigned t = 0; unsigned tcount = m_triangles.size(); for ( t = 0; t < tcount; t++ ) { m_triangles[t]->m_marked = false; } unsigned g = 0; unsigned gcount = m_groups.size(); for ( g = 0; g < gcount; g++ ) { Group * grp = m_groups[g]; for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { m_triangles[ *it ]->m_marked = true; } } for ( t = 0; t < tcount; t++ ) { if ( ! m_triangles[t]->m_marked ) { triangles.push_back( t ); } } return triangles; } list Model::getGroupTriangles( unsigned groupNumber ) const { list triangles; if ( groupNumber < m_groups.size() ) { Group * grp = m_groups[ groupNumber ]; for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { triangles.push_back( *it ); } } return triangles; } int Model::getTriangleGroup( unsigned triangleNumber ) const { for ( unsigned g = 0; g < m_groups.size(); g++ ) { Group * grp = m_groups[g]; if ( grp->m_triangleIndices.end() != grp->m_triangleIndices.find( triangleNumber ) ) { return g; } } // Triangle is not in a group return -1; } const char * Model::getGroupName( unsigned groupNum ) const { if ( groupNum >= 0 && groupNum < m_groups.size() ) { return m_groups[ groupNum ]->m_name.c_str(); } else { return NULL; } } int Model::getGroupByName( const char * const groupName, bool ignoreCase ) const { int (*compare)(const char *, const char *); compare = ignoreCase ? strcasecmp : strcmp; int groupNumber = -1; for ( unsigned g = 0; g < m_groups.size(); g++ ) { if ( compare( groupName, m_groups[g]->m_name.c_str() ) == 0 ) { groupNumber = g; break; } } return groupNumber; } uint8_t Model::getGroupSmooth( unsigned groupNum ) const { if ( groupNum < m_groups.size() ) { return m_groups[ groupNum ]->m_smooth; } else { return 0; } } uint8_t Model::getGroupAngle( unsigned groupNum ) const { if ( groupNum < m_groups.size() ) { return m_groups[ groupNum ]->m_angle; } else { return 180; } } mm3d-1.3.7/src/libmm3d/drawcontext.h0000644000175000017500000000230310744511346014137 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __DRAWCONTEXT_H #define __DRAWCONTEXT_H #include #include typedef void * ContextT; class DrawingContext { public: ContextT m_context; std::vector m_textures; bool m_valid; int m_currentTexture; }; typedef std::list< DrawingContext * > DrawingContextList; #endif // __DRAWCONTEXT_H mm3d-1.3.7/src/libmm3d/sorted_list.h0000644000175000017500000000721110744511346014133 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __SORTED_LIST_H #define __SORTED_LIST_H #include template class sorted_list : public std::vector { public: typedef int (*CompareFunction)( const T &, const T & ); sorted_list(); virtual ~sorted_list(); void insert_sorted( const T & val ); bool find_sorted( const T & val, unsigned & index ) const; protected: }; template sorted_list::sorted_list() { } template sorted_list::~sorted_list() { } template void sorted_list::insert_sorted( const T & val ) { typename std::vector< T >::iterator it; unsigned len = this->size(); if ( len == 0 || (*this)[len-1] < val ) { push_back( val ); } else { for ( it = this->begin(); it != this->end(); it ++) { if ( val < *it ) { break; } } this->insert( it, val ); } } template bool sorted_list::find_sorted( const T & val, unsigned & index ) const { int top = this->size() - 1; int bot = 0; int mid = top / 2; while ( bot <= top ) { if ( (*this)[mid] == val ) { index = mid; return true; } if ( (*this)[mid] < val ) { bot = mid + 1; mid = (top + bot) / 2; } else { top = mid - 1; mid = (top + bot) / 2; } } return false; } template class sorted_ptr_list : public std::vector { public: typedef int (*CompareFunction)( const T &, const T & ); sorted_ptr_list(); virtual ~sorted_ptr_list(); void insert_sorted( const T & val ); bool find_sorted( const T & val, unsigned & index ) const; protected: }; template sorted_ptr_list::sorted_ptr_list() { } template sorted_ptr_list::~sorted_ptr_list() { } template void sorted_ptr_list::insert_sorted( const T & val ) { typename std::vector< T >::iterator it; unsigned len = this->size(); if ( len == 0 || *((*this)[len-1]) < *val ) { push_back( val ); } else { for ( it = this->begin(); it != this->end(); it ++) { if ( *val < *(*it) ) { break; } } this->insert( it, val ); } } template bool sorted_ptr_list::find_sorted( const T & val, unsigned & index ) const { int top = this->size() - 1; int bot = 0; int mid = top / 2; while ( bot <= top ) { if ( *(*this)[mid] == *val ) { index = mid; return true; } if ( *(*this)[mid] < *val ) { bot = mid + 1; mid = (top + bot) / 2; } else { top = mid - 1; mid = (top + bot) / 2; } } return false; } #endif // __SORTED_LIST_H mm3d-1.3.7/src/libmm3d/misc.cc0000644000175000017500000003200611000471707012661 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "misc.h" #include "mm3dconfig.h" //#include "sysconf.h" #include "log.h" #include "mm3dport.h" #include "sorted_list.h" #include #include #include #include #include #include #include #include #include using std::string; void replaceSlash( char * str ) { if ( str ) { for ( int n = 0; str[n]; n++ ) { if ( str[n] == '/' ) { str[n] = '\\'; } } } } void replaceSlash( std::string & str ) { for ( unsigned n = 0; n < str.size(); n++ ) { if ( str[n] == '/' ) { str[n] = '\\'; } } } void replaceBackslash( std::string & str ) { for ( unsigned n = 0; n < str.size(); n++ ) { if ( str[n] == '\\' ) { str[n] = '/'; } } } void replaceBackslash( char * str ) { if ( str ) { for ( int n = 0; str[n]; n++ ) { if ( str[n] == '\\' ) { str[n] = '/'; } } } } string getFilePathFromPath( const char * path ) { string rval; char * temp = strdup( path ); rval = PORT_dirname( temp ); free( temp ); return rval; } string getFileNameFromPath( const char * path ) { string rval; char * temp = strdup( path ); rval = PORT_basename( temp ); free( temp ); return rval; } bool pathIsAbsolute( const char * path ) { if ( path == NULL ) { return false; } if ( isalpha( path[0] ) && path[1] == ':' ) { return true; } return ( path[0] == '/' || path[0] == '\\' ); } string normalizePath( const char * path, const char * pwd ) { string rval; string fullPath; if ( pathIsAbsolute( path ) ) { fullPath = path; } else { if ( pwd ) { fullPath = pwd; fullPath += DIR_SLASH; fullPath += path; } else { char * tempPwd = new char[PATH_MAX]; getcwd( tempPwd, PATH_MAX ); fullPath = tempPwd; fullPath += DIR_SLASH; fullPath += path; delete[] tempPwd; } } char resolved[ PATH_MAX ]; if ( PORT_realpath( fullPath.c_str(), resolved, PATH_MAX ) ) { rval = resolved; } else { rval = path; } return rval; } string getRelativePath( const char * b, const char * p ) { if ( b && p ) { std::string base(b); std::string path(p); replaceBackslash(base); replaceBackslash(path); if ( pathIsAbsolute( path.c_str() ) && !base.empty() ) { // Append a / if that's not the last char if ( base[ base.size() - 1 ] != '/' ) { base += "/"; } int lastSlash = 0; int t = 0; int len = (int) (base.size() < path.size()) ? base.size() : path.size(); for ( t = 0; t < len; t++ ) { if ( base[t] != path[t] ) { break; } else { if ( base[t] == '/' ) { lastSlash = t; } } } // Back up to lastSlash and prepend "../" for each '/' remaining in base string rval = "./"; size_t offset = lastSlash; while ( (offset = base.find('/', offset + 1 )) < base.size() ) { rval += "../"; } rval += &path[ lastSlash + 1 ]; log_debug( "relative path is %s\n", rval.c_str() ); return rval; } return path; // already relative } return ""; // Error } string getAbsolutePath( const char * base, const char * path ) { if ( base && path ) { if ( !pathIsAbsolute( path ) ) { char * bptr = (char *) malloc(sizeof(char) * (strlen(base) + 2) ); strcpy( bptr, base ); replaceBackslash(bptr); // Append a / if that's not the last char if ( bptr[ strlen(base) - 1 ] != '/' ) { strcat( bptr, "/" ); } int off = 0; bool removed = false; do { removed = false; if ( strncmp( &path[off], "./", 2 ) == 0 ) { off += 2; removed = true; } else if ( strncmp( &path[off], "../", 3 ) == 0 ) { removed = true; off += 3; // remove trailing slash bptr[ strlen(bptr) - 1 ] = '\0'; // truncate after new last slash char * temp = strrchr( bptr, '/' ); if ( temp ) { temp += 1; temp[0] = '\0'; } } } while( removed ); string rval = string( bptr ) + &path[off]; free( bptr ); log_debug( "absolute path is %s\n", rval.c_str() ); return rval; } else { return path; // Already absolute } } return ""; // Error } string fixAbsolutePath( const char * base, const char * path ) { if ( base && path ) { if ( pathIsAbsolute( path ) ) { string rval; char * temp = strrchr( path, '/' ); if ( temp ) { temp++; if ( temp[0] ) { string rval = temp; DIR * dp = opendir( base ); if ( dp ) { struct dirent * d; while ( (d = readdir(dp )) != NULL ) { if ( strcasecmp( d->d_name, temp ) == 0 ) { rval = d->d_name; break; } } closedir( dp ); } else { log_error( "%s: %s\n", base, strerror(errno) ); } return rval; } } } return path; } return ""; // error /* if ( base && path ) { if ( path[0] == '/' || strcasecmp( path, "c:" ) == 0 ) { char * bptr = (char *) malloc(sizeof(char) * (strlen(base) + 2) ); strcpy( bptr, base ); // Append a / if that's not the last char if ( bptr[ strlen(base) - 1 ] != '/' ) { strcat( bptr, "/" ); } bool stillLooking = true; string newBase; char * ptr; while ( stillLooking ) { newBase = bptr; ptr = strchr( ptr, '/' ); while ( ptr ) { ptr++; if ( ptr[0] ) { stillLooking = false; break; } else { string dirent = _findDirent( &ptr[0] ); if ( dirent.c_str()[0] != '\0' ) { } } ptr = strchr( ptr, '/' ); } } if ( strcmp( base, newBase.c_str() ) != 0 ) { // newBase isn't equal return newBase; } } return path; } else { return ""; } */ } string fixFileCase( const char * path, const char * file ) { std::string rval = file; DIR * dp = opendir( path ); if ( dp ) { struct dirent * d; while ( (d = readdir( dp )) != NULL ) { if ( strcasecmp( d->d_name, file ) == 0 ) { rval = d->d_name; break; } } closedir( dp ); } return rval; } void normalizePath( const char * filename, std::string & fullName, std::string & fullPath, std::string & baseName ) { char path[PATH_MAX]; PORT_realpath( filename, path, PATH_MAX ); replaceBackslash( path ); fullName = path; fullPath = PORT_dirname( path ); strcpy( path, fullName.c_str() ); baseName = PORT_basename( (char *) filename ); replaceBackslash( baseName ); } std::string replaceExtension( const char * infile, const char * ext ) { std::string rval = removeExtension( infile ); rval += '.'; rval += ext; return rval; } std::string removeExtension( const char * infile ) { std::string rval = infile; size_t i = rval.rfind( '.' ); size_t len = rval.size(); if ( i > 0 && i < len ) { size_t slash = rval.rfind( '/' ); if ( slash > len ) slash = rval.rfind( '\\' ); if ( slash > len || i > slash + 1 ) rval.resize(i); } return rval; } void getFileList( std::list & l, const char * const path, const char * const name ) { sorted_list sl; unsigned len = strlen( name ); DIR * dp = opendir( path ); if ( dp ) { struct dirent * d; while ( (d = readdir( dp )) != NULL ) { if ( strncasecmp( d->d_name, name, len ) == 0 ) { sl.insert_sorted( d->d_name ); } } closedir( dp ); } for ( unsigned t = 0; t < sl.size(); t++ ) { l.push_back( sl[t] ); } } bool file_exists( const char * filename ) { struct stat statbuf; if ( PORT_lstat( filename, &statbuf ) == 0 ) { return true; } else { return false; } } bool is_directory( const char * filename ) { struct stat statbuf; if ( PORT_lstat( filename, &statbuf ) == 0 ) { DIR * dp = opendir( filename ); // Don't check S_ISDIR, could be symlink if ( dp ) { closedir( dp ); return true; } } return false; } int mkpath( const char * filename, mode_t mode ) { if ( filename && filename[0] ) { char * str = strdup( filename ); size_t len = strlen( filename ); size_t offset = 1; do { while ( filename[ offset ] != '\0' && filename[ offset ] != '/' && filename[ offset ] != '\\' ) { offset++; } strcpy ( str, filename ); str[ offset ] = '\0'; PORT_mkdir( str, mode ); offset++; } while ( offset <= len ); free( str ); } return 0; } size_t utf8len( const char * str ) { size_t len = 0; size_t pos = 0; while ( str && str[pos] != 0 ) { unsigned char ch = ((unsigned char) str[pos]) & 0xc0; if ( ch == 0 || ch == 0x40 || ch == 0xc0 ) { len++; } pos++; } return len; } size_t utf8len( const std::string & str ) { return utf8len( str.c_str() ); } // Truncate at "len" utf8 characters void utf8strtrunc( char * str, size_t len ) { if ( str ) { size_t pos = 0; size_t n = 0; size_t slen = strlen(str); while ( pos < slen && n < len ) { unsigned char ch = ((unsigned char) str[pos]) & 0xc0; if ( (ch & 0xc0) == 0xc0 ) { n++; ch = str[pos]; if ( (ch & 0xe0) == 0xc0 ) pos += 2; else if ( (ch & 0xf0) == 0xe0 ) pos += 3; else if ( (ch & 0xf8) == 0xf0 ) pos += 4; } else { n++; pos++; } } utf8chrtrunc( str, pos ); } } void utf8strtrunc( std::string & str, size_t len ) { size_t pos = 0; size_t n = 0; size_t slen = str.size(); while ( pos < slen && n < len ) { unsigned char ch = ((unsigned char) str[pos]) & 0xc0; if ( (ch & 0xc0) == 0xc0 ) { n++; ch = str[pos]; if ( (ch & 0xe0) == 0xc0 ) pos += 2; else if ( (ch & 0xf0) == 0xe0 ) pos += 3; else if ( (ch & 0xf8) == 0xf0 ) pos += 4; } else { n++; pos++; } } utf8chrtrunc( str, pos ); } // Truncate at "len" bytes (C characters) void utf8chrtrunc( char * str, size_t len ) { // If we're truncating while ( len > 0 && (((unsigned char) str[len] & 0xc0 )) == 0x80 ) { len--; } str[len] = '\0'; } void utf8chrtrunc( std::string & str, size_t len ) { while ( len > 0 && (((unsigned char) str[len] & 0xc0 )) == 0x80 ) { len--; } if ( len < str.size() ) str.resize(len); } mm3d-1.3.7/src/libmm3d/modelundo.h0000644000175000017500000012615510744511346013577 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __MODELUNDO_H #define __MODELUNDO_H #include "undo.h" #include "model.h" #include "glmath.h" #include "sorted_list.h" #include #include using std::list; using std::string; class Model; class ModelUndo : public Undo { public: ModelUndo() { s_allocated++; }; virtual ~ModelUndo() { s_allocated--; }; virtual void undo( Model * ) = 0; virtual void redo( Model * ) = 0; static int s_allocated; }; class MU_NoOp : public Undo { public: MU_NoOp() {}; virtual ~MU_NoOp() {}; void undo( Model * ) {}; void redo( Model * ) {}; bool combine( Undo * ); // Actually has an implementation unsigned size() { return sizeof(MU_NoOp); }; }; class MU_TranslateSelected : public ModelUndo { public: MU_TranslateSelected(); virtual ~MU_TranslateSelected(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size() { return sizeof(MU_TranslateSelected); }; void setMatrix( const Matrix & rhs ); Matrix getMatrix() const { return m_matrix; }; private: Matrix m_matrix; }; class MU_RotateSelected : public ModelUndo { public: MU_RotateSelected(); virtual ~MU_RotateSelected(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size() { return sizeof(MU_RotateSelected); }; void setMatrixPoint( const Matrix & rhs, double * point ); Matrix getMatrix() const { return m_matrix; }; private: Matrix m_matrix; double m_point[3]; }; class MU_ApplyMatrix : public ModelUndo { public: MU_ApplyMatrix(); virtual ~MU_ApplyMatrix(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size() { return sizeof(MU_ApplyMatrix); }; void setMatrix( const Matrix & mat, Model::OperationScopeE scope, bool animations ); Matrix getMatrix() const { return m_matrix; }; private: Matrix m_matrix; Model::OperationScopeE m_scope; bool m_animations; }; class MU_SelectionMode : public ModelUndo { public: MU_SelectionMode(); virtual ~MU_SelectionMode(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setSelectionMode( Model::SelectionModeE mode, Model::SelectionModeE oldMode ) { m_mode = mode; m_oldMode = oldMode; }; private: Model::SelectionModeE m_mode; Model::SelectionModeE m_oldMode; }; class MU_Select : public ModelUndo { public: MU_Select( Model::SelectionModeE mode ); virtual ~MU_Select(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); Model::SelectionModeE getSelectionMode() const { return m_mode; }; void setSelectionDifference( int number, bool selected, bool oldSelected ); void toggle( int number ); unsigned diffCount() { return m_diff.size(); }; private: typedef struct _SelectionDifference_t { int number; bool selected; bool oldSelected; bool operator< ( const struct _SelectionDifference_t & rhs ) const { return ( this->number < rhs.number ); } bool operator== ( const struct _SelectionDifference_t & rhs ) const { return ( this->number == rhs.number ); } } SelectionDifferenceT; typedef sorted_list< SelectionDifferenceT > SelectionDifferenceList; Model::SelectionModeE m_mode; SelectionDifferenceList m_diff; }; class MU_Hide : public ModelUndo { public: MU_Hide( Model::SelectionModeE mode ); virtual ~MU_Hide(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); Model::SelectionModeE getSelectionMode() const { return m_mode; }; void setHideDifference( int number, bool visible ); private: typedef struct _HideDifference_t { int number; bool visible; } HideDifferenceT; typedef list< HideDifferenceT > HideDifferenceList; Model::SelectionModeE m_mode; HideDifferenceList m_diff; }; class MU_InvertNormal : public ModelUndo { public: MU_InvertNormal(); virtual ~MU_InvertNormal(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void addTriangle( int triangle ); private: list m_triangles; }; class MU_MovePrimitive : public ModelUndo { public: MU_MovePrimitive(); virtual ~MU_MovePrimitive(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); typedef enum _MoveType_e { MT_Vertex, MT_Joint, MT_Point, MT_Projection }; typedef enum _MoveType_e MoveTypeE; void addMovePrimitive( MoveTypeE, int i, double x, double y, double z, double oldx, double oldy, double oldz ); private: typedef struct _MovePrimitive_t { int number; double x; double y; double z; double oldx; double oldy; double oldz; MoveTypeE type; bool operator< ( const struct _MovePrimitive_t & rhs ) const { return ( this->number < rhs.number || ( this->number == rhs.number && this->type < rhs.type ) ); }; bool operator== ( const struct _MovePrimitive_t & rhs ) const { return ( this->number == rhs.number && this->type == rhs.type ); }; } MovePrimitiveT; typedef sorted_list MovePrimitiveList; MovePrimitiveList m_objects; }; class MU_SetPointRotation : public ModelUndo { public: MU_SetPointRotation(); virtual ~MU_SetPointRotation(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setPointRotation( int p, double x, double y, double z, double oldx, double oldy, double oldz ); private: int number; double x; double y; double z; double oldx; double oldy; double oldz; }; class MU_SetPointTranslation : public ModelUndo { public: MU_SetPointTranslation(); virtual ~MU_SetPointTranslation(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setPointTranslation( int p, double x, double y, double z, double oldx, double oldy, double oldz ); private: int number; double x; double y; double z; double oldx; double oldy; double oldz; }; class MU_SetTexture : public ModelUndo { public: MU_SetTexture(); virtual ~MU_SetTexture(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setTexture( unsigned groupNumber, int newTexture, int oldTexture ); private: typedef struct _SetTexture_t { unsigned groupNumber; int newTexture; int oldTexture; } SetTextureT; typedef list SetTextureList; SetTextureList m_list; }; class MU_AddVertex : public ModelUndo { public: MU_AddVertex(); virtual ~MU_AddVertex(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addVertex( unsigned index, Model::Vertex * vertex ); private: typedef struct _AddVertex_t { unsigned index; Model::Vertex * vertex; } AddVertexT; typedef list AddVertexList; AddVertexList m_list; }; class MU_AddTriangle : public ModelUndo { public: MU_AddTriangle(); virtual ~MU_AddTriangle(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addTriangle( unsigned index, Model::Triangle * ); private: typedef struct _AddTriangle_t { unsigned index; Model::Triangle * triangle; } AddTriangleT; typedef list AddTriangleList; AddTriangleList m_list; }; class MU_AddGroup : public ModelUndo { public: MU_AddGroup(); virtual ~MU_AddGroup(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addGroup( unsigned index, Model::Group * ); private: typedef struct _AddGroup_t { unsigned index; Model::Group * group; } AddGroupT; typedef list AddGroupList; AddGroupList m_list; }; class MU_AddTexture : public ModelUndo { public: MU_AddTexture(); virtual ~MU_AddTexture(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addTexture( unsigned index, Model::Material * ); private: typedef struct _AddTexture_t { unsigned index; Model::Material * texture; } AddTextureT; typedef list AddTextureList; AddTextureList m_list; }; class MU_SetTextureCoords : public ModelUndo { public: MU_SetTextureCoords(); virtual ~MU_SetTextureCoords(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void addTextureCoords( unsigned triangle, unsigned vertexIndex, float s, float t, float oldS, float oldT ); private: typedef struct _SetTextureCoords_t { unsigned triangle; unsigned vertexIndex; float t; float s; float oldT; float oldS; bool operator< ( const struct _SetTextureCoords_t & rhs ) const { return ( this->triangle < rhs.triangle || (this->triangle == rhs.triangle && this->vertexIndex < rhs.vertexIndex ) ); }; bool operator == ( const struct _SetTextureCoords_t & rhs ) const { return ( this->triangle == rhs.triangle && this->vertexIndex == rhs.vertexIndex ); }; } SetTextureCoordsT; typedef sorted_list STCList; STCList m_list; }; class MU_AddToGroup : public ModelUndo { public: MU_AddToGroup(); virtual ~MU_AddToGroup(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void addToGroup( unsigned groupNum, unsigned triangleNum ); private: typedef struct _AddToGroup_t { unsigned groupNum; unsigned triangleNum; } AddToGroupT; typedef list AddToGroupList; AddToGroupList m_list; }; class MU_RemoveFromGroup : public ModelUndo { public: MU_RemoveFromGroup(); virtual ~MU_RemoveFromGroup(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void removeFromGroup( unsigned groupNum, unsigned triangleNum ); private: typedef struct _RemoveFromGroup_t { unsigned groupNum; unsigned triangleNum; } RemoveFromGroupT; typedef list RemoveFromGroupList; RemoveFromGroupList m_list; }; class MU_DeleteTriangle : public ModelUndo { public: MU_DeleteTriangle(); virtual ~MU_DeleteTriangle(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deleteTriangle( unsigned triangleNum, Model::Triangle * triangle ); private: typedef struct _DeleteTriangle_t { unsigned triangleNum; Model::Triangle * triangle; } DeleteTriangleT; typedef list DeleteTriangleList; DeleteTriangleList m_list; }; class MU_DeleteVertex : public ModelUndo { public: MU_DeleteVertex(); virtual ~MU_DeleteVertex(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deleteVertex( unsigned vertexNum, Model::Vertex * vertex ); private: typedef struct _DeleteVertex_t { unsigned vertexNum; Model::Vertex * vertex; } DeleteVertexT; typedef list DeleteVertexList; DeleteVertexList m_list; }; class MU_DeleteBoneJoint : public ModelUndo { public: MU_DeleteBoneJoint(); virtual ~MU_DeleteBoneJoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deleteBoneJoint( unsigned jointNum, Model::Joint * joint ); private: unsigned m_jointNum; Model::Joint * m_joint; }; class MU_DeletePoint : public ModelUndo { public: MU_DeletePoint(); virtual ~MU_DeletePoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deletePoint( unsigned pointNum, Model::Point * point ); private: unsigned m_pointNum; Model::Point * m_point; }; class MU_DeleteProjection : public ModelUndo { public: MU_DeleteProjection(); virtual ~MU_DeleteProjection(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deleteProjection( unsigned projNum, Model::TextureProjection * proj ); private: unsigned m_projNum; Model::TextureProjection * m_proj; }; class MU_AddBoneJoint : public ModelUndo { public: MU_AddBoneJoint(); virtual ~MU_AddBoneJoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addBoneJoint( unsigned jointNum, Model::Joint * joint ); private: unsigned m_jointNum; Model::Joint * m_joint; }; class MU_AddPoint : public ModelUndo { public: MU_AddPoint(); virtual ~MU_AddPoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addPoint( unsigned pointNum, Model::Point * point ); private: unsigned m_pointNum; Model::Point * m_point; }; class MU_AddProjection : public ModelUndo { public: MU_AddProjection(); virtual ~MU_AddProjection(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addProjection( unsigned pointNum, Model::TextureProjection * point ); private: unsigned m_projNum; Model::TextureProjection * m_proj; }; class MU_DeleteGroup : public ModelUndo { public: MU_DeleteGroup(); virtual ~MU_DeleteGroup(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deleteGroup( unsigned groupNum, Model::Group * group ); private: typedef struct _DeleteGroup_t { unsigned groupNum; Model::Group * group; } DeleteGroupT; typedef list DeleteGroupList; DeleteGroupList m_list; }; class MU_DeleteTexture : public ModelUndo { public: MU_DeleteTexture(); virtual ~MU_DeleteTexture(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deleteTexture( unsigned textureNum, Model::Material * texture ); private: typedef struct _DeleteTexture_t { unsigned textureNum; Model::Material * texture; } DeleteTextureT; typedef list DeleteTextureList; DeleteTextureList m_list; }; class MU_SetLightProperties : public ModelUndo { public: enum _LightType_e { LightAmbient = 0, LightDiffuse, LightSpecular, LightEmissive, LightTypeMax }; typedef enum _LightType_e LightTypeE; MU_SetLightProperties(); virtual ~MU_SetLightProperties(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setLightProperties( unsigned textureNum, LightTypeE type, const float * newLight, const float * oldLight ); private: typedef struct _LightProperties_t { unsigned textureNum; float newLight[ LightTypeMax ][4]; float oldLight[ LightTypeMax ][4]; bool isSet[ LightTypeMax ]; } LightPropertiesT; typedef list LightPropertiesList; list m_list; }; class MU_SetShininess : public ModelUndo { public: MU_SetShininess(); virtual ~MU_SetShininess(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setShininess( unsigned textureNum, const float & newValue, const float & oldValue ); private: typedef struct _Shininess_t { unsigned textureNum; float oldValue; float newValue; } ShininessT; typedef list ShininessList; list m_list; }; class MU_SetTextureName : public ModelUndo { public: MU_SetTextureName(); virtual ~MU_SetTextureName(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setTextureName( unsigned textureNum, const char * newName, const char * oldName ); private: unsigned m_textureNum; string m_newName; string m_oldName; }; class MU_SetTriangleVertices : public ModelUndo { public: MU_SetTriangleVertices(); virtual ~MU_SetTriangleVertices(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setTriangleVertices( unsigned triangleNum, unsigned newV1, unsigned newV2, unsigned newV3, unsigned oldV1, unsigned oldV2, unsigned oldV3 ); private: typedef struct _TriangleVertices_t { unsigned triangleNum; unsigned newVertices[3]; unsigned oldVertices[3]; } TriangleVerticesT; typedef list TriangleVerticesList; TriangleVerticesList m_list; }; class MU_SubdivideSelected : public ModelUndo { public: MU_SubdivideSelected(); virtual ~MU_SubdivideSelected(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size() { return sizeof( MU_SubdivideSelected ); }; private: }; class MU_SubdivideTriangle : public ModelUndo { public: MU_SubdivideTriangle(); virtual ~MU_SubdivideTriangle(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void subdivide( unsigned a, unsigned b, unsigned c, unsigned d ); void addVertex( unsigned v ); private: typedef struct _SubdivideTriangle_t { unsigned a; unsigned b; unsigned c; unsigned d; } SubdivideTriangleT; typedef list SubdivideTriangleList; SubdivideTriangleList m_list; list m_vlist; }; class MU_ChangeAnimState : public ModelUndo { public: MU_ChangeAnimState(); virtual ~MU_ChangeAnimState(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setState( Model::AnimationModeE newMode, Model::AnimationModeE oldMode, unsigned anim, unsigned frame ); protected: Model::AnimationModeE m_newMode; Model::AnimationModeE m_oldMode; unsigned m_anim; unsigned m_frame; }; class MU_SetAnimName : public ModelUndo { public: MU_SetAnimName(); virtual ~MU_SetAnimName(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setName( Model::AnimationModeE mode, unsigned animNum, const char * newName, const char * oldName ); private: Model::AnimationModeE m_mode; unsigned m_animNum; string m_newName; string m_oldName; }; class MU_SetAnimFrameCount : public ModelUndo { public: MU_SetAnimFrameCount(); virtual ~MU_SetAnimFrameCount(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setAnimFrameCount( Model::AnimationModeE m, unsigned animNum, unsigned newCount, unsigned oldCount ); private: Model::AnimationModeE m_mode; unsigned m_animNum; unsigned m_newCount; unsigned m_oldCount; }; class MU_SetAnimFPS : public ModelUndo { public: MU_SetAnimFPS(); virtual ~MU_SetAnimFPS(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setFPS( Model::AnimationModeE mode, unsigned animNum, double newFps, double oldFps ); private: Model::AnimationModeE m_mode; unsigned m_animNum; double m_newFPS; double m_oldFPS; }; class MU_SetAnimKeyframe : public ModelUndo { public: MU_SetAnimKeyframe(); virtual ~MU_SetAnimKeyframe(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setAnimationData( const unsigned & anim, const unsigned & frame, const bool & isRotation ); void addBoneJoint( int j, bool isNew, double x, double y, double z, double oldx, double oldy, double oldz ); private: typedef struct _SetKeyframe_t { int number; bool isNew; double x; double y; double z; double oldx; double oldy; double oldz; bool operator< ( const struct _SetKeyframe_t & rhs ) const { return ( this->number < rhs.number ); }; bool operator== ( const struct _SetKeyframe_t & rhs ) const { return ( this->number == rhs.number ); }; } SetKeyFrameT; typedef sorted_list SetKeyframeList; SetKeyframeList m_keyframes; unsigned m_anim; unsigned m_frame; bool m_isRotation; }; class MU_DeleteKeyframe : public ModelUndo { public: MU_DeleteKeyframe(); virtual ~MU_DeleteKeyframe(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void setAnimationData( const unsigned & anim ); void deleteKeyframe( Model::Keyframe * keyframe ); private: typedef list DeleteKeyframeList; DeleteKeyframeList m_list; unsigned m_anim; }; class MU_SetJointName : public ModelUndo { public: MU_SetJointName(); virtual ~MU_SetJointName(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setName( unsigned joint, const char * newName, const char * oldName ); private: unsigned m_joint; string m_newName; string m_oldName; }; class MU_SetPointName : public ModelUndo { public: MU_SetPointName(); virtual ~MU_SetPointName(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setName( unsigned point, const char * newName, const char * oldName ); private: unsigned m_point; string m_newName; string m_oldName; }; class MU_SetProjectionName : public ModelUndo { public: MU_SetProjectionName(); virtual ~MU_SetProjectionName(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setName( unsigned projection, const char * newName, const char * oldName ); private: unsigned m_projection; string m_newName; string m_oldName; }; class MU_SetProjectionType : public ModelUndo { public: MU_SetProjectionType(); virtual ~MU_SetProjectionType(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setType( unsigned projection, int newType, int oldType ); private: unsigned m_projection; int m_newType; int m_oldType; }; class MU_MoveFrameVertex : public ModelUndo { public: MU_MoveFrameVertex(); virtual ~MU_MoveFrameVertex(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setAnimationData( const unsigned & anim, const unsigned & frame ); void addVertex( int v, double x, double y, double z, double oldx, double oldy, double oldz ); private: typedef struct _MoveFrameVertex_t { int number; double x; double y; double z; double oldx; double oldy; double oldz; bool operator< ( const struct _MoveFrameVertex_t & rhs ) const { return ( this->number < rhs.number ); }; bool operator== ( const struct _MoveFrameVertex_t & rhs ) const { return ( this->number == rhs.number ); }; } MoveFrameVertexT; typedef sorted_list MoveFrameVertexList; MoveFrameVertexList m_vertices; unsigned m_anim; unsigned m_frame; }; class MU_MoveFramePoint : public ModelUndo { public: MU_MoveFramePoint(); virtual ~MU_MoveFramePoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setAnimationData( const unsigned & anim, const unsigned & frame ); void addPoint( int p, double x, double y, double z, double oldx, double oldy, double oldz ); private: typedef struct _MoveFramePoint_t { int number; double x; double y; double z; double oldx; double oldy; double oldz; bool operator< ( const struct _MoveFramePoint_t & rhs ) const { return ( this->number < rhs.number ); }; bool operator== ( const struct _MoveFramePoint_t & rhs ) const { return ( this->number == rhs.number ); }; } MoveFramePointT; typedef sorted_list MoveFramePointList; MoveFramePointList m_points; unsigned m_anim; unsigned m_frame; }; class MU_RotateFramePoint : public ModelUndo { public: MU_RotateFramePoint(); virtual ~MU_RotateFramePoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setAnimationData( const unsigned & anim, const unsigned & frame ); void addPointRotation( int p, double x, double y, double z, double oldx, double oldy, double oldz ); private: typedef struct _RotateFramePoint_t { int number; double x; double y; double z; double oldx; double oldy; double oldz; bool operator< ( const struct _RotateFramePoint_t & rhs ) const { return ( this->number < rhs.number ); }; bool operator== ( const struct _RotateFramePoint_t & rhs ) const { return ( this->number == rhs.number ); }; } RotateFramePointT; typedef sorted_list RotateFramePointList; RotateFramePointList m_points; unsigned m_anim; unsigned m_frame; }; class MU_AddFrameAnimFrame : public ModelUndo { public: MU_AddFrameAnimFrame(); virtual ~MU_AddFrameAnimFrame(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void setAnimationData( const unsigned & anim ); void addFrame( const unsigned & frame, Model::FrameAnimData * data ); private: typedef struct _AddFrame_t { unsigned frame; Model::FrameAnimData * data; } AddFrameT; typedef list FrameDataList; FrameDataList m_list; unsigned m_anim; }; class MU_DeleteFrameAnimFrame : public ModelUndo { public: MU_DeleteFrameAnimFrame(); virtual ~MU_DeleteFrameAnimFrame(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void setAnimationData( const unsigned & anim ); void deleteFrame( const unsigned & frame, Model::FrameAnimData * data ); private: typedef struct _DeleteFrame_t { unsigned frame; Model::FrameAnimData * data; } DeleteFrameT; typedef list FrameDataList; FrameDataList m_list; unsigned m_anim; }; class MU_SetPositionInfluence : public ModelUndo { public: MU_SetPositionInfluence(); virtual ~MU_SetPositionInfluence(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setPositionInfluence( bool isAdd, const Model::Position & pos, unsigned index, const Model::InfluenceT & influence ); private: bool m_isAdd; Model::Position m_pos; unsigned m_index; Model::InfluenceT m_influence; }; class MU_UpdatePositionInfluence : public ModelUndo { public: MU_UpdatePositionInfluence(); virtual ~MU_UpdatePositionInfluence(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void updatePositionInfluence( const Model::Position & pos, const Model::InfluenceT & newInf, const Model::InfluenceT & oldInf ); private: Model::Position m_pos; Model::InfluenceT m_newInf; Model::InfluenceT m_oldInf; }; class MU_SetVertexBoneJoint : public ModelUndo { public: MU_SetVertexBoneJoint(); virtual ~MU_SetVertexBoneJoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setVertexBoneJoint( const unsigned & vertex, const int & newBone, const int & oldBone ); private: typedef struct _SetJoint_t { unsigned vertex; int newBone; int oldBone; } SetJointT; typedef list SetJointList; SetJointList m_list; }; class MU_SetPointBoneJoint : public ModelUndo { public: MU_SetPointBoneJoint(); virtual ~MU_SetPointBoneJoint(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setPointBoneJoint( const unsigned & point, const int & newBone, const int & oldBone ); private: typedef struct _SetJoint_t { unsigned point; int newBone; int oldBone; } SetJointT; typedef list SetJointList; SetJointList m_list; }; class MU_SetTriangleProjection : public ModelUndo { public: MU_SetTriangleProjection(); virtual ~MU_SetTriangleProjection(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setTriangleProjection( const unsigned & vertex, const int & newProj, const int & oldProj ); private: typedef struct _SetProjection_t { unsigned triangle; int newProj; int oldProj; } SetProjectionT; typedef list SetProjectionList; SetProjectionList m_list; }; class MU_AddAnimation : public ModelUndo { public: MU_AddAnimation(); virtual ~MU_AddAnimation(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void redoRelease(); unsigned size(); void addAnimation( const unsigned & anim, Model::SkelAnim * skelanim ); void addAnimation( const unsigned & anim, Model::FrameAnim * frameanim ); private: unsigned m_anim; Model::SkelAnim * m_skelAnim; Model::FrameAnim * m_frameAnim; }; class MU_DeleteAnimation : public ModelUndo { public: MU_DeleteAnimation(); virtual ~MU_DeleteAnimation(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); void undoRelease(); unsigned size(); void deleteAnimation( const unsigned & anim, Model::SkelAnim * skelanim ); void deleteAnimation( const unsigned & anim, Model::FrameAnim * frameanim ); private: unsigned m_anim; Model::SkelAnim * m_skelAnim; Model::FrameAnim * m_frameAnim; }; class MU_SetJointParent : public ModelUndo { public: MU_SetJointParent(); virtual ~MU_SetJointParent(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size() { return sizeof(MU_SetJointParent); }; void setJointParent( unsigned joint, int newParent, int oldParent ); protected: unsigned m_joint; int m_newParent; int m_oldParent; }; class MU_SetJointRotation : public ModelUndo { public: MU_SetJointRotation(); virtual ~MU_SetJointRotation(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size() { return sizeof(MU_SetJointRotation); }; void setJointRotation( const unsigned & joint, const double * newRotation, const double * oldRotation ); protected: unsigned m_joint; double m_newRotation[3]; double m_oldRotation[3]; }; class MU_SetJointTranslation : public ModelUndo { public: MU_SetJointTranslation(); virtual ~MU_SetJointTranslation(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size() { return sizeof(MU_SetJointTranslation); }; void setJointTranslation( const unsigned & joint, const double * newTranslation, const double * oldTranslation ); protected: unsigned m_joint; double m_newTranslation[3]; double m_oldTranslation[3]; }; class MU_SetProjectionUp : public ModelUndo { public: MU_SetProjectionUp(); virtual ~MU_SetProjectionUp(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size() { return sizeof(MU_SetProjectionUp); }; void setProjectionUp( const unsigned & proj, const double * newUp, const double * oldUp ); protected: unsigned m_proj; double m_newUp[3]; double m_oldUp[3]; }; class MU_SetProjectionSeam : public ModelUndo { public: MU_SetProjectionSeam(); virtual ~MU_SetProjectionSeam(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size() { return sizeof(MU_SetProjectionSeam); }; void setProjectionSeam( const unsigned & proj, const double * newSeam, const double * oldSeam ); protected: unsigned m_proj; double m_newSeam[3]; double m_oldSeam[3]; }; class MU_SetProjectionRange : public ModelUndo { public: MU_SetProjectionRange(); virtual ~MU_SetProjectionRange(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size() { return sizeof(MU_SetProjectionRange); }; void setProjectionRange( const unsigned & proj, double newXMin, double newYMin, double newXMax, double newYMax, double oldXMin, double oldYMin, double oldXMax, double oldYMax ); protected: unsigned m_proj; double m_newRange[4]; double m_oldRange[4]; }; class MU_SetGroupSmooth : public ModelUndo { public: MU_SetGroupSmooth(); virtual ~MU_SetGroupSmooth(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setGroupSmooth( const unsigned & group, const uint8_t & newSmooth, const uint8_t & oldSmooth ); private: typedef struct _SetSmooth_t { unsigned group; uint8_t newSmooth; uint8_t oldSmooth; } SetSmoothT; typedef list SetSmoothList; SetSmoothList m_list; }; class MU_SetGroupAngle : public ModelUndo { public: MU_SetGroupAngle(); virtual ~MU_SetGroupAngle(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setGroupAngle( const unsigned & group, const uint8_t & newAngle, const uint8_t & oldAngle ); private: typedef struct _SetAngle_t { unsigned group; uint8_t newAngle; uint8_t oldAngle; } SetAngleT; typedef list SetAngleList; SetAngleList m_list; }; class MU_SetGroupName : public ModelUndo { public: MU_SetGroupName(); virtual ~MU_SetGroupName(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setGroupName( unsigned groupNum, const char * newName, const char * oldName ); private: unsigned m_groupNum; string m_newName; string m_oldName; }; class MU_MoveAnimation : public ModelUndo { public: MU_MoveAnimation(); virtual ~MU_MoveAnimation(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void moveAnimation( const Model::AnimationModeE & mode, const unsigned & oldIndex, const unsigned & newIndex ); private: Model::AnimationModeE m_mode; unsigned m_oldIndex; unsigned m_newIndex; }; class MU_SetFrameAnimVertexCount : public ModelUndo { public: MU_SetFrameAnimVertexCount(); virtual ~MU_SetFrameAnimVertexCount(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size(); void setCount( const unsigned & newCount, const unsigned & oldCount ); private: unsigned m_newCount; unsigned m_oldCount; }; class MU_SetFrameAnimPointCount : public ModelUndo { public: MU_SetFrameAnimPointCount(); virtual ~MU_SetFrameAnimPointCount(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ) { return false; }; unsigned size(); void setCount( const unsigned & newCount, const unsigned & oldCount ); private: unsigned m_newCount; unsigned m_oldCount; }; class MU_SetMaterialClamp : public ModelUndo { public: MU_SetMaterialClamp(); virtual ~MU_SetMaterialClamp(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setMaterialClamp( const unsigned & material, const bool & isS, const bool & newClamp, const bool & oldClamp ); private: unsigned m_material; bool m_isS; bool m_oldClamp; bool m_newClamp; }; class MU_SetMaterialTexture : public ModelUndo { public: MU_SetMaterialTexture(); virtual ~MU_SetMaterialTexture(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setMaterialTexture( const unsigned & material, Texture * newTexture, Texture * oldTexture ); private: unsigned m_material; Texture * m_oldTexture; Texture * m_newTexture; }; class MU_SetBackgroundImage : public ModelUndo { public: MU_SetBackgroundImage(); virtual ~MU_SetBackgroundImage(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setBackgroundImage( const unsigned & index, const char * newFilename, const char * oldFilename ); private: unsigned m_index; string m_newFilename; string m_oldFilename; }; class MU_SetBackgroundScale : public ModelUndo { public: MU_SetBackgroundScale(); virtual ~MU_SetBackgroundScale(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setBackgroundScale( const unsigned & index, float newScale, float oldScale ); private: unsigned m_index; float m_newScale; float m_oldScale; }; class MU_SetBackgroundCenter : public ModelUndo { public: MU_SetBackgroundCenter(); virtual ~MU_SetBackgroundCenter(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void setBackgroundCenter( const unsigned & index, float newX, float newY, float newZ, float oldX, float oldY, float oldZ ); private: unsigned m_index; float m_new[3]; float m_old[3]; }; class MU_AddMetaData : public ModelUndo { public: MU_AddMetaData(); virtual ~MU_AddMetaData(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void addMetaData( const std::string & key, const std::string & value ); private: std::string m_key; std::string m_value; }; class MU_UpdateMetaData : public ModelUndo { public: MU_UpdateMetaData(); virtual ~MU_UpdateMetaData(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void updateMetaData( const std::string & key, const std::string & newValue, const std::string & oldValue ); private: std::string m_key; std::string m_newValue; std::string m_oldValue; }; class MU_ClearMetaData : public ModelUndo { public: MU_ClearMetaData(); virtual ~MU_ClearMetaData(); void undo( Model * ); void redo( Model * ); bool combine( Undo * ); unsigned size(); void clearMetaData( const Model::MetaDataList & list ); private: Model::MetaDataList m_list; }; #endif // __MODELUNDO_H mm3d-1.3.7/src/libmm3d/model_inner.cc0000644000175000017500000010206111025503223014214 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "texture.h" #include "log.h" #include #include using __gnu_cxx::hash_set; static bool _model_recycle = true; int Model::Vertex::s_allocated = 0; int Model::Triangle::s_allocated = 0; int Model::Group::s_allocated = 0; int Model::Material::s_allocated = 0; int Model::Keyframe::s_allocated = 0; int Model::Joint::s_allocated = 0; int Model::Point::s_allocated = 0; int Model::TextureProjection::s_allocated = 0; int Model::SkelAnim::s_allocated = 0; int Model::FrameAnim::s_allocated = 0; int Model::FrameAnimVertex::s_allocated = 0; int Model::FrameAnimPoint::s_allocated = 0; list Model::Vertex::s_recycle; list Model::Triangle::s_recycle; list Model::Group::s_recycle; list Model::Material::s_recycle; list Model::Keyframe::s_recycle; list Model::Joint::s_recycle; list Model::Point::s_recycle; list Model::SkelAnim::s_recycle; list Model::FrameAnim::s_recycle; list Model::FrameAnimVertex::s_recycle; list Model::FrameAnimPoint::s_recycle; const double EQ_TOLERANCE = 0.00001; template bool floatCompareVector( T * lhs, T * rhs, size_t len, double tolerance = EQ_TOLERANCE ) { for ( size_t index = 0; index < len; ++index ) if ( fabs( lhs[index] - rhs[index] ) > tolerance ) return false; return true; } static bool influencesMatch( const Model::InfluenceList & lhs, const Model::InfluenceList & rhs, int propBits, double tolerance ) { typedef std::map InfluenceMap; InfluenceMap lhsInfMap; Model::InfluenceList::const_iterator it; for ( it = lhs.begin(); it != lhs.end(); ++it ) { lhsInfMap[ it->m_boneId ] = *it; } for ( it = rhs.begin(); it != rhs.end(); ++it ) { InfluenceMap::const_iterator lhs_it = lhsInfMap.find( it->m_boneId ); if ( lhs_it == lhsInfMap.end() ) { log_warning( "match failed on missing lhs bone %d\n", it->m_boneId ); return false; } // This doesn't matter if we only care about weights if ( propBits & Model::PropInfluences ) { if ( lhs_it->second.m_type != it->m_type ) { log_warning( "match failed on influence type (%d vs %d) for bone %d\n", lhs_it->second.m_type, it->m_type, it->m_boneId ); return false; } } if ( fabs( lhs_it->second.m_weight - it->m_weight ) > tolerance ) { log_warning( "match failed on influence weight (%f vs %f) for bone %d\n", (float) lhs_it->second.m_weight, (float) it->m_weight, it->m_boneId ); return false; } lhsInfMap.erase( it->m_boneId ); } if ( !lhsInfMap.empty() ) { log_warning( "match failed on missing rhs bone %d\n", lhsInfMap.begin()->second.m_boneId ); return false; } return true; } Model::Vertex::Vertex() : m_selected( false ), m_visible( true ), m_free( false ), m_drawSource( m_coord ) { s_allocated++; } Model::Vertex::~Vertex() { s_allocated--; } void Model::Vertex::init() { m_selected = false; m_visible = true; m_free = false; m_drawSource = m_coord; m_influences.clear(); } int Model::Vertex::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::Vertex::stats() { log_debug( "Vertex: %d/%d\n", s_recycle.size(), s_allocated ); } Model::Vertex * Model::Vertex::get() { if ( ! s_recycle.empty() ) { Vertex * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else { return new Vertex(); } } void Model::Vertex::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } bool Model::Vertex::propEqual(const Vertex & rhs, int propBits, double tolerance ) const { if ( (propBits & PropCoords) != 0 ) { if ( !floatCompareVector( m_coord, rhs.m_coord, 3, tolerance ) ) return false; } if ( (propBits & PropSelection) ) if ( m_selected != rhs.m_selected ) return false; if ( (propBits & PropVisibility) ) if ( m_visible != rhs.m_visible ) return false; if ( (propBits & PropFree) ) if ( m_free != rhs.m_free ) return false; // FIXME apply this to points also if ( (propBits & (PropInfluences | PropWeights)) != 0 ) { if ( !influencesMatch( m_influences, rhs.m_influences, propBits, tolerance ) ) return false; } return true; } Model::Triangle::Triangle() : m_selected( false ), m_visible( true ), m_marked( false ), m_projection( -1 ) { init(); s_allocated++; } Model::Triangle::~Triangle() { s_allocated--; } void Model::Triangle::init() { m_s[0] = 0.0; m_t[0] = 1.0; m_s[1] = 0.0; m_t[1] = 0.0; m_s[2] = 1.0; m_t[2] = 0.0; m_selected = false; m_marked = false; m_visible = true; m_projection = -1; m_flatSource = m_flatNormals; m_normalSource[0] = m_finalNormals[0]; m_normalSource[1] = m_finalNormals[1]; m_normalSource[2] = m_finalNormals[2]; } int Model::Triangle::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::Triangle::stats() { log_debug( "Triangle: %d/%d\n", s_recycle.size(), s_allocated ); } Model::Triangle * Model::Triangle::get() { if ( ! s_recycle.empty() ) { Triangle * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else { return new Triangle(); } } void Model::Triangle::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } bool Model::Triangle::propEqual(const Triangle & rhs, int propBits, double tolerance ) const { if ( (propBits & PropVertices) != 0 ) { if ( m_vertexIndices[0] != rhs.m_vertexIndices[0] || m_vertexIndices[1] != rhs.m_vertexIndices[1] || m_vertexIndices[2] != rhs.m_vertexIndices[2] ) { return false; } } if ( (propBits & PropProjections) != 0 ) if ( m_projection != rhs.m_projection ) return false; if ( (propBits & PropTexCoords) != 0 ) { for ( int i = 0; i < 3; ++i ) { if ( fabs( m_s[i] - rhs.m_s[i] ) > tolerance ) return false; if ( fabs( m_t[i] - rhs.m_t[i] ) > tolerance ) return false; } } if ( (propBits & PropSelection) != 0 ) if ( m_selected != rhs.m_selected ) return false; if ( (propBits & PropVisibility) != 0 ) if ( m_visible != rhs.m_visible ) return false; return true; } Model::Group::Group() : m_materialIndex( -1 ), m_smooth( 255 ), m_angle( 89 ), m_selected( false ), m_visible( true ) { s_allocated++; } Model::Group::~Group() { s_allocated--; } void Model::Group::init() { m_materialIndex = -1; m_smooth = 255; m_angle = 89; m_selected = false; m_visible = true; m_name.clear(); m_triangleIndices.clear(); } int Model::Group::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::Group::stats() { log_debug( "Group: %d/%d\n", s_recycle.size(), s_allocated ); } Model::Group * Model::Group::get() { if ( ! s_recycle.empty() ) { Group * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else { return new Group(); } } void Model::Group::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } bool Model::Group::propEqual(const Group & rhs, int propBits, double tolerance ) const { if ( (propBits & PropTriangles) != 0 ) if ( m_triangleIndices != rhs.m_triangleIndices ) return false; if ( (propBits & PropNormals) != 0 ) { if ( m_smooth != rhs.m_smooth ) return false; if ( m_angle != rhs.m_angle ) return false; } if ( (propBits & PropMaterials) != 0 ) if ( m_materialIndex != rhs.m_materialIndex ) return false; if ( (propBits & PropName) != 0 ) if ( m_name != rhs.m_name ) return false; if ( (propBits & PropSelection) != 0 ) if ( m_selected != rhs.m_selected ) return false; if ( (propBits & PropVisibility) != 0 ) if ( m_visible != rhs.m_visible ) return false; return true; } Model::Material::Material() : m_type( MATTYPE_TEXTURE ), m_sClamp( false ), m_tClamp( false ), m_texture( 0 ), m_textureData( NULL ) { s_allocated++; } Model::Material::~Material() { s_allocated--; // Do NOT free m_textureData. TextureManager does that } void Model::Material::init() { m_name.clear(); m_filename.clear(); m_alphaFilename.clear(); m_textureData = NULL; m_texture = 0; m_type = MATTYPE_TEXTURE; m_sClamp = false; m_tClamp = false; } int Model::Material::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::Material::stats() { log_debug( "Material: %d/%d\n", s_recycle.size(), s_allocated ); } Model::Material * Model::Material::get() { if ( ! s_recycle.empty() ) { Material * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else { return new Material(); } } void Model::Material::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } bool Model::Material::propEqual(const Material & rhs, int propBits, double tolerance ) const { if ( (propBits & PropType) != 0 ) if ( m_type != rhs.m_type ) return false; if ( (propBits & PropLighting) != 0 ) { if ( !floatCompareVector( m_ambient, rhs.m_ambient, 4, tolerance ) ) return false; if ( !floatCompareVector( m_diffuse, rhs.m_diffuse, 4, tolerance ) ) return false; if ( !floatCompareVector( m_specular, rhs.m_specular, 4, tolerance ) ) return false; if ( !floatCompareVector( m_emissive, rhs.m_emissive, 4, tolerance ) ) return false; if ( fabs(m_shininess - rhs.m_shininess) > tolerance ) return false; } if ( (propBits & PropClamp) != 0 ) { if ( m_sClamp != rhs.m_sClamp ) return false; if ( m_tClamp != rhs.m_tClamp ) return false; } // Color is unused if ( (propBits & PropPixels) != 0 ) { // If one is NULL, the other must be also if ( (m_textureData == NULL) != (rhs.m_textureData == NULL) ) return false; // Compare texture itself if ( m_textureData ) { Texture::CompareResultT res; if ( !m_textureData->compare( rhs.m_textureData, &res, 0 ) ) return false; // Name and filename should not be an issue (should match material) } else { // If no texture data, must not be a texture-mapped material if ( m_type == Model::Material::MATTYPE_TEXTURE ) return false; } } if ( (propBits & PropName) != 0 ) if ( m_name != rhs.m_name ) return false; if ( (propBits & PropPaths) != 0 ) if ( m_filename != rhs.m_filename ) return false; if ( (propBits & PropPaths) != 0 ) if ( m_alphaFilename != rhs.m_alphaFilename ) return false; return true; } Model::Keyframe::Keyframe() { s_allocated++; } Model::Keyframe::~Keyframe() { s_allocated--; } void Model::Keyframe::init() { } int Model::Keyframe::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::Keyframe::stats() { log_debug( "Keyframe: %d/%d\n", s_recycle.size(), s_allocated ); } Model::Keyframe * Model::Keyframe::get() { if ( ! s_recycle.empty() ) { Keyframe * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else { return new Keyframe(); } } void Model::Keyframe::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } bool Model::Keyframe::propEqual(const Keyframe & rhs, int propBits, double tolerance ) const { if ( m_jointIndex != rhs.m_jointIndex ) return false; if ( (propBits & PropType) != 0 ) if ( m_isRotation != rhs.m_isRotation ) return false; if ( (propBits & PropTime) != 0 ) { if ( m_frame != rhs.m_frame ) return false; if ( fabs( m_time - rhs.m_time ) > tolerance ) return false; } if ( (m_isRotation && (propBits & PropRotation) != 0) || (!m_isRotation && (propBits & PropCoords) != 0) ) if ( !floatCompareVector( m_parameter, rhs.m_parameter, 3, tolerance ) ) return false; return true; } Model::Joint::Joint() { s_allocated++; init(); } Model::Joint::~Joint() { init(); s_allocated--; } void Model::Joint::init() { m_selected = false; m_visible = true; } Model::Joint * Model::Joint::get() { if ( ! s_recycle.empty() ) { Joint * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else { return new Joint(); } } void Model::Joint::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } int Model::Joint::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::Joint::stats() { log_debug( "Joint: %d/%d\n", s_recycle.size(), s_allocated ); } bool Model::Joint::propEqual(const Joint & rhs, int propBits, double tolerance ) const { if ( (propBits & PropRotation) != 0 ) { for ( unsigned i = 0; i < 3; i++ ) { if ( fabs( m_localRotation[i] - rhs.m_localRotation[i]) > tolerance ) return false; } } if ( (propBits & PropCoords) != 0 ) { for ( unsigned i = 0; i < 3; i++ ) { if ( fabs( m_localTranslation[i] - rhs.m_localTranslation[i]) > tolerance ) return false; } } if ( m_parent != rhs.m_parent ) return false; if ( (propBits & PropName) != 0 ) if ( m_name != rhs.m_name ) return false; if ( (propBits & PropSelection) != 0 ) if ( m_selected != rhs.m_selected ) return false; if ( (propBits & PropVisibility) != 0 ) if ( m_visible != rhs.m_visible ) return false; return true; } Model::Point::Point() { s_allocated++; init(); } Model::Point::~Point() { init(); s_allocated--; } void Model::Point::init() { m_selected = false; m_visible = true; m_type = 0; m_kfTrans[0] = 0.0; m_kfTrans[1] = 0.0; m_kfTrans[2] = 0.0; m_kfRot[0] = 0.0; m_kfRot[1] = 0.0; m_kfRot[2] = 0.0; m_drawSource = m_trans; m_rotSource = m_rot; m_influences.clear(); } Model::Point * Model::Point::get() { if ( ! s_recycle.empty() ) { Point * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else { return new Point(); } } void Model::Point::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } int Model::Point::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::Point::stats() { log_debug( "Point: %d/%d\n", s_recycle.size(), s_allocated ); } bool Model::Point::propEqual(const Point & rhs, int propBits, double tolerance ) const { if ( (propBits & PropCoords) != 0 ) if ( !floatCompareVector( m_trans, rhs.m_trans, 3, tolerance ) ) return false; if ( (propBits & PropRotation) != 0 ) if ( !floatCompareVector( m_rot, rhs.m_rot, 3, tolerance ) ) return false; if ( (propBits & PropName) != 0 ) if ( m_name != rhs.m_name ) return false; if ( (propBits & PropType) != 0 ) if ( m_type != rhs.m_type ) return false; if ( (propBits & PropSelection) != 0 ) if ( m_selected != rhs.m_selected ) return false; if ( (propBits & PropVisibility) != 0 ) if ( m_visible != rhs.m_visible ) return false; if ( (propBits & (PropInfluences | PropWeights)) != 0 ) { InfluenceList::const_iterator lhs_it = m_influences.begin(); InfluenceList::const_iterator rhs_it = rhs.m_influences.begin(); for ( ; lhs_it != m_influences.end() && rhs_it != rhs.m_influences.end(); ++lhs_it, ++rhs_it ) { // This doesn't matter if we only care about weights if ( propBits & PropInfluences ) if ( lhs_it->m_type != rhs_it->m_type ) return false; // This matters if we're comparing influences or weights if ( lhs_it->m_boneId != rhs_it->m_boneId ) return false; if ( fabs( lhs_it->m_weight - rhs_it->m_weight ) > tolerance ) return false; } if ( lhs_it != m_influences.end() || rhs_it != rhs.m_influences.end() ) return false; } return true; } Model::TextureProjection::TextureProjection() { s_allocated++; init(); } Model::TextureProjection::~TextureProjection() { init(); s_allocated--; } void Model::TextureProjection::init() { m_selected = false; m_type = 0; m_range[0][0] = 0.0; m_range[0][1] = 0.0; m_range[1][0] = 1.0; m_range[1][1] = 1.0; } Model::TextureProjection * Model::TextureProjection::get() { /* if ( ! s_recycle.empty() ) { TextureProjection * v = s_recycle.front(); s_recycle.pop_front(); v->init(); return v; } else */ { return new TextureProjection(); } } void Model::TextureProjection::release() { /* if ( _model_recycle ) { s_recycle.push_front( this ); } else */ { delete this; } } int Model::TextureProjection::flush() { int c = 0; /* list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); */ return c; } void Model::TextureProjection::stats() { log_debug( "TextureProjection: %d/%d\n", 0, s_allocated ); } bool Model::TextureProjection::propEqual(const TextureProjection & rhs, int propBits, double tolerance ) const { if ( (propBits & PropType) != 0 ) if ( m_type != rhs.m_type ) return false; if ( (propBits & PropCoords) != 0 ) if ( !floatCompareVector( m_pos, rhs.m_pos, 3, tolerance ) ) return false; if ( (propBits & PropRotation) != 0 ) { if ( !floatCompareVector( m_upVec, rhs.m_upVec, 3, tolerance ) ) return false; if ( !floatCompareVector( m_seamVec, rhs.m_seamVec, 3, tolerance ) ) return false; } if ( (propBits & PropDimensions) != 0 ) { if ( !floatCompareVector( m_range[0], rhs.m_range[0], 2, tolerance ) ) return false; if ( !floatCompareVector( m_range[1], rhs.m_range[1], 2, tolerance ) ) return false; } if ( (propBits & PropName) != 0 ) if ( m_name != rhs.m_name ) return false; if ( (propBits & PropSelection) != 0 ) if ( m_selected != rhs.m_selected ) return false; return true; } Model::SkelAnim::SkelAnim() : m_fps( 10.0 ) { s_allocated++; init(); } Model::SkelAnim::~SkelAnim() { s_allocated--; init(); } void Model::SkelAnim::init() { m_name = "Skel"; m_validNormals = false; releaseData(); } void Model::SkelAnim::releaseData() { for ( unsigned j = 0; j < m_jointKeyframes.size(); j++ ) { for ( unsigned k = 0; k < m_jointKeyframes[j].size(); k++ ) { m_jointKeyframes[j][k]->release(); } m_jointKeyframes[j].clear(); } m_jointKeyframes.clear(); } Model::SkelAnim * Model::SkelAnim::get() { if ( s_recycle.empty() ) { return new SkelAnim; } else { SkelAnim * val = s_recycle.front(); s_recycle.pop_front(); return val; } } void Model::SkelAnim::release() { if ( _model_recycle ) { init(); s_recycle.push_front( this ); } else { delete this; } } int Model::SkelAnim::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::SkelAnim::stats() { log_debug( "SkelAnim: %d/%d\n", s_recycle.size(), s_allocated ); } bool Model::SkelAnim::propEqual(const SkelAnim & rhs, int propBits, double tolerance ) const { if ( (propBits & PropName) != 0 ) { if ( m_name != rhs.m_name ) { log_warning( "match failed at anim name, lhs = '%s', rhs = '%s'\n", m_name.c_str(), rhs.m_name.c_str() ); return false; } } if ( (propBits & PropTime) != 0 ) { if ( fabs( m_fps - rhs.m_fps ) > tolerance ) { log_warning( "match failed at anim fps, lhs = %f, rhs = %f\n", (float) m_fps, (float) rhs.m_fps ); return false; } } if ( (propBits & PropDimensions) != 0 ) { if ( m_frameCount != rhs.m_frameCount ) { log_warning( "match failed at anim frame count, lhs = %d, rhs = %d\n", m_frameCount, rhs.m_frameCount ); return false; } } if ( (propBits & (PropCoords | PropRotation | PropType)) != 0 ) { if ( m_jointKeyframes.size() != rhs.m_jointKeyframes.size() ) { log_warning( "match failed at anim keyframe size, lhs = %d, rhs = %d\n", m_jointKeyframes.size(), rhs.m_jointKeyframes.size() ); return false; } JointKeyframeList::const_iterator lhs_it = m_jointKeyframes.begin(); JointKeyframeList::const_iterator rhs_it = rhs.m_jointKeyframes.begin(); for ( ; lhs_it != m_jointKeyframes.end() && rhs_it != m_jointKeyframes.end(); ++lhs_it, ++rhs_it ) { if ( lhs_it->size() != rhs_it->size() ) return false; KeyframeList::const_iterator l = lhs_it->begin(); KeyframeList::const_iterator r = rhs_it->begin(); for ( ; l != lhs_it->end() && r != rhs_it->end(); ++l, ++r ) { if ( !(*l)->propEqual( **r, propBits, tolerance ) ) return false; } } } return true; } void Model::FrameAnimData::releaseData() { if ( m_frameVertices ) { for ( unsigned v = 0; v < m_frameVertices->size(); v++ ) { (*m_frameVertices)[v]->release(); } m_frameVertices->clear(); } if ( m_framePoints ) { for ( unsigned p = 0; p < m_framePoints->size(); p++ ) { (*m_framePoints)[p]->release(); } m_framePoints->clear(); } } Model::FrameAnim::FrameAnim() : m_fps( 10.0 ) { s_allocated++; init(); } Model::FrameAnim::~FrameAnim() { s_allocated--; init(); } void Model::FrameAnim::init() { m_name = "Frame"; m_validNormals = false; releaseData(); } Model::FrameAnim * Model::FrameAnim::get() { if ( s_recycle.empty() ) { return new FrameAnim; } else { FrameAnim * val = s_recycle.front(); s_recycle.pop_front(); return val; } } void Model::FrameAnim::release() { if ( _model_recycle ) { init(); s_recycle.push_front( this ); } else { delete this; } } void Model::FrameAnim::releaseData() { while ( ! m_frameData.empty() ) { m_frameData.back()->releaseData(); delete m_frameData.back()->m_frameVertices; delete m_frameData.back()->m_framePoints; delete m_frameData.back(); m_frameData.pop_back(); } m_frameData.clear(); } int Model::FrameAnim::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::FrameAnim::stats() { log_debug( "FrameAnim: %d/%d\n", s_recycle.size(), s_allocated ); } bool Model::FrameAnim::propEqual(const FrameAnim & rhs, int propBits, double tolerance ) const { if ( (propBits & PropName) != 0 ) { if ( m_name != rhs.m_name ) { log_warning( "match failed at anim name lhs '%s', rhs '%s'\n", m_name.c_str(), rhs.m_name.c_str() ); return false; } } if ( (propBits & PropTime) != 0 ) { if ( fabs( m_fps - rhs.m_fps ) > tolerance ) { log_warning( "match failed at anim fps lhs %f, rhs %f\n", (float) m_fps, (float) rhs.m_fps ); return false; } } if ( (propBits & (PropCoords | PropRotation)) != 0 ) { if ( m_frameData.size() != rhs.m_frameData.size() ) { log_warning( "match failed at anim frame size lhs %d, rhs %d\n", m_frameData.size(), rhs.m_frameData.size() ); return false; } FrameAnimDataList::const_iterator lhs_it = m_frameData.begin(); FrameAnimDataList::const_iterator rhs_it = rhs.m_frameData.begin(); for ( ; lhs_it != m_frameData.end() && rhs_it != m_frameData.end(); ++lhs_it, ++rhs_it ) { if ( !(*lhs_it)->propEqual( **rhs_it, propBits, tolerance ) ) { log_warning( "match failed at frame %d\n", lhs_it - m_frameData.begin() ); return false; } } } return true; } Model::FrameAnimVertex::FrameAnimVertex() { s_allocated++; init(); } Model::FrameAnimVertex::~FrameAnimVertex() { s_allocated--; } void Model::FrameAnimVertex::init() { for ( unsigned t = 0; t < 3; t++ ) { m_coord[t] = 0; m_normal[t] = 0; } } Model::FrameAnimVertex * Model::FrameAnimVertex::get() { if ( s_recycle.empty() ) { return new FrameAnimVertex; } else { FrameAnimVertex * val = s_recycle.front(); val->init(); s_recycle.pop_front(); return val; } } void Model::FrameAnimVertex::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } int Model::FrameAnimVertex::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::FrameAnimVertex::stats() { log_debug( "FrameAnimVertex: %d/%d\n", s_recycle.size(), s_allocated ); } bool Model::FrameAnimVertex::propEqual(const FrameAnimVertex & rhs, int propBits, double tolerance ) const { if ( (propBits & PropCoords) != 0 ) { if ( !floatCompareVector( m_coord, rhs.m_coord, 3, tolerance ) ) { log_warning( "frame anim vertex coord mismatch, lhs (%f,%f,%f) rhs (%f,%f,%f)\n", (float) m_coord[0], (float) m_coord[1], (float) m_coord[2], (float) rhs.m_coord[0], (float) rhs.m_coord[1], (float) rhs.m_coord[2] ); return false; } } return true; } Model::FrameAnimPoint::FrameAnimPoint() { s_allocated++; init(); } Model::FrameAnimPoint::~FrameAnimPoint() { s_allocated--; } void Model::FrameAnimPoint::init() { for ( unsigned t = 0; t < 3; t++ ) { m_trans[t] = 0; m_rot[t] = 0; } } Model::FrameAnimPoint * Model::FrameAnimPoint::get() { if ( s_recycle.empty() ) { return new FrameAnimPoint; } else { FrameAnimPoint * val = s_recycle.front(); val->init(); s_recycle.pop_front(); return val; } } void Model::FrameAnimPoint::release() { if ( _model_recycle ) { s_recycle.push_front( this ); } else { delete this; } } int Model::FrameAnimPoint::flush() { int c = 0; list::iterator it = s_recycle.begin(); while ( it != s_recycle.end() ) { delete *it; it++; c++; } s_recycle.clear(); return c; } void Model::FrameAnimPoint::stats() { log_debug( "FrameAnimPoint: %d/%d\n", s_recycle.size(), s_allocated ); } bool Model::FrameAnimPoint::propEqual(const FrameAnimPoint & rhs, int propBits, double tolerance ) const { if ( (propBits & PropCoords) != 0 ) { if ( !floatCompareVector( m_trans, rhs.m_trans, 3, tolerance ) ) { log_warning( "frame anim point translation mismatch, lhs (%f,%f,%f) rhs (%f,%f,%f) tolerance (%f)\n", (float) m_trans[0], (float) m_trans[1], (float) m_trans[2], (float) rhs.m_trans[0], (float) rhs.m_trans[1], (float) rhs.m_trans[2], (float) tolerance ); return false; } } if ( (propBits & PropRotation) != 0 ) { if ( !floatCompareVector( m_rot, rhs.m_rot, 3, tolerance ) ) { log_warning( "frame anim point rotation mismatch, lhs (%f,%f,%f) rhs (%f,%f,%f)\n", (float) m_rot[0], (float) m_rot[1], (float) m_rot[2], (float) rhs.m_rot[0], (float) rhs.m_rot[1], (float) rhs.m_rot[2] ); return false; } } return true; } bool Model::FrameAnimData::propEqual(const FrameAnimData & rhs, int propBits, double tolerance ) const { if ( (propBits & (PropCoords | PropRotation)) != 0 ) { if ( m_frameVertices->size() != rhs.m_frameVertices->size() ) { log_warning( "anim frame vertex size mismatch lhs %d, rhs %d\n", m_frameVertices->size(), rhs.m_frameVertices->size() ); return false; } if ( m_framePoints->size() != rhs.m_framePoints->size() ) { log_warning( "anim frame point size mismatch lhs %d, rhs %d\n", m_framePoints->size(), rhs.m_framePoints->size() ); return false; } FrameAnimVertexList::iterator lv = m_frameVertices->begin(); FrameAnimVertexList::iterator rv = rhs.m_frameVertices->begin(); for ( ; lv != m_frameVertices->end(), rv != rhs.m_frameVertices->end(); ++lv, ++rv ) { if ( !(*lv)->propEqual( **rv, propBits, tolerance ) ) { log_warning( "anim frame vertex mismatch at %d\n", lv - m_frameVertices->begin() ); return false; } } FrameAnimPointList::iterator lp = m_framePoints->begin(); FrameAnimPointList::iterator rp = rhs.m_framePoints->begin(); for ( ; lp != m_framePoints->end(), rp != rhs.m_framePoints->end(); ++lp, ++rp ) { if ( !(*lp)->propEqual( **rp, propBits, tolerance ) ) { log_warning( "anim frame point mismatch at %d\n", lp - m_framePoints->begin() ); return false; } } } return true; } Model::FormatData::~FormatData() { if ( data ) { delete[] data; data = NULL; } } void Model::FormatData::serialize() { // Implement this if you derive from Model::FormatData // The default implementation assumes that data never changes // after it is assigned, so it doesn't need to be re-serialized } #ifdef MM3D_EDIT Model::BackgroundImage::BackgroundImage() : m_scale( 30.0f ) { m_center[0] = 0.0f; m_center[1] = 0.0f; m_center[2] = 0.0f; } Model::BackgroundImage::~BackgroundImage() { } bool Model::BackgroundImage::propEqual(const BackgroundImage & rhs, int propBits, double tolerance ) const { if ( (propBits & PropPaths) != 0 ) if ( m_filename != rhs.m_filename ) return false; if ( (propBits & PropScale) != 0 ) if ( fabs( m_scale - rhs.m_scale ) > tolerance ) return false; if ( (propBits & PropCoords) != 0 ) if ( !floatCompareVector( m_center, rhs.m_center, 3, tolerance ) ) return false; return true; } #endif // MM3D_EDIT mm3d-1.3.7/src/libmm3d/mm3dreg.cc0000644000175000017500000002361510744511346013302 00000000000000#ifdef WIN32 /* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "mm3dreg.h" #include #include namespace Mm3dReg { RegErrorE Mm3dRegKey::winToMm3dError( LONG err ) { switch ( err ) { case ERROR_SUCCESS: return RE_NONE; break; case ERROR_FILE_NOT_FOUND: return RE_NO_KEY; break; case ERROR_ACCESS_DENIED: return RE_ACCESS_DENIED; break; case ERROR_INVALID_HANDLE: return RE_INVALID_HANDLE; break; default: break; } return RE_UNKNOWN; } RegErrorE Mm3dRegKey::deleteKey( HKEY hKey, const char * keyName ) { LONG err = RegDeleteKey( hKey, keyName ); return winToMm3dError( err ); } int Mm3dRegKey::getRegistryInt( HKEY hKey, const char * keyName, const char * valueName ) { Mm3dRegKey key( hKey, keyName, RA_READ ); if ( key.getLastError() == RE_NONE ) { int val = 0; key.getValueInt( valueName, val ); return val; } else { return 0; } } std::string Mm3dRegKey::getRegistryString( HKEY hKey, const char * keyName, const char * valueName ) { Mm3dRegKey key( hKey, keyName, RA_READ ); if ( key.getLastError() == RE_NONE ) { std::string val = ""; key.getValueString( valueName, val ); return val; } else { return ""; } } RegErrorE Mm3dRegKey::setRegistryInt( HKEY hKey, const char * keyName, const char * valueName, int val ) { RegErrorE err = RE_NONE; Mm3dRegKey key( hKey, keyName, RA_WRITE ); err = key.getLastError(); if ( err == RE_NONE ) { err = key.setValueInt( valueName, val ); } return err; } RegErrorE Mm3dRegKey::setRegistryString( HKEY hKey, const char * keyName, const char * valueName, const std::string & val ) { RegErrorE err = RE_NONE; Mm3dRegKey key( hKey, keyName, RA_WRITE ); err = key.getLastError(); if ( err == RE_NONE ) { err = key.setValueString( valueName, val ); } return err; } Mm3dRegKey::Mm3dRegKey( HKEY hKey, const char * subKey, RegAccessE ra ) : m_hkey( 0 ) { openKey( hKey, subKey, ra ); } Mm3dRegKey::~Mm3dRegKey() { if ( m_hkey ) { RegCloseKey( m_hkey ); m_hkey = 0; } } RegErrorE Mm3dRegKey::deleteSubKey( const char * keyName ) { RegErrorE rval = RE_NONE; if ( m_hkey ) { LONG err = RegDeleteKey( m_hkey, keyName ); rval = winToMm3dError( err ); m_error = rval; } return rval; } RegErrorE Mm3dRegKey::deleteValue( const char * valueName ) { RegErrorE rval = RE_NONE; if ( m_hkey ) { LONG err = RegDeleteValue( m_hkey, valueName ); rval = winToMm3dError( err ); m_error = rval; } return rval; } RegErrorE Mm3dRegKey::getValueType( const char * value, DWORD & valueType ) { if ( m_hkey ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; valueType = 0; err = RegQueryValueEx( m_hkey, value, NULL, &valueType, NULL, NULL ); rval = winToMm3dError( err ); m_error = rval; return rval; } else { return RE_NO_KEY; } } RegErrorE Mm3dRegKey::getValueString( const char * value, std::string & valueStr ) { if ( m_hkey ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; DWORD valueType = REG_SZ; DWORD ptrLen = 128; char * ptr = NULL; do { if ( ptr ) { free( ptr ); } ptr = (char *) malloc( ptrLen ); err = RegQueryValueEx( m_hkey, value, NULL, &valueType, (LPBYTE) ptr, &ptrLen ); } while ( err == ERROR_MORE_DATA ); rval = winToMm3dError( err ); if ( err == ERROR_SUCCESS ) { if ( valueType == REG_SZ ) { valueStr = ptr; } else { rval = RE_WRONG_TYPE; } } free( ptr ); m_error = rval; return rval; } else { return RE_NO_KEY; } } RegErrorE Mm3dRegKey::getValueInt( const char * value, int & valueInt ) { if ( m_hkey ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; DWORD valueType = REG_DWORD; DWORD valueDWord = 0; DWORD ptrLen = sizeof( valueDWord ); err = RegQueryValueEx( m_hkey, value, NULL, &valueType, (LPBYTE) &valueDWord, &ptrLen ); rval = winToMm3dError( err ); if ( err == ERROR_SUCCESS ) { if ( valueType == REG_DWORD ) { valueInt = (int) valueDWord; } else { rval = RE_WRONG_TYPE; } } m_error = rval; return rval; } else { return RE_NO_KEY; } } RegErrorE Mm3dRegKey::setValueString( const char * value, const std::string & valueStr ) { if ( m_hkey ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; DWORD len = valueStr.size(); err = RegSetValueEx( m_hkey, value, 0, REG_SZ, (LPBYTE) valueStr.c_str(), len ); rval = winToMm3dError( err ); m_error = rval; return rval; } else { return RE_NO_KEY; } } RegErrorE Mm3dRegKey::setValueInt( const char * value, int valueInt ) { if ( m_hkey ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; DWORD valueDWord = (DWORD) valueInt; err = RegSetValueEx( m_hkey, value, 0, REG_DWORD, (LPBYTE) &valueDWord, sizeof( valueInt ) ); rval = winToMm3dError( err ); m_error = rval; return rval; } else { return RE_NO_KEY; } } RegErrorE Mm3dRegKey::getValueNames( RegStringList & nameList ) { nameList.clear(); if ( m_hkey ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; DWORD keyCount; DWORD keyLen; err = RegQueryInfoKey( m_hkey, NULL, NULL, NULL, NULL, NULL, NULL, &keyCount, &keyLen, NULL, NULL, NULL ); keyLen += 10; if ( err == ERROR_SUCCESS ) { char * ptr = (char *) malloc( keyLen ); for ( DWORD t = 0; t < keyCount; t++ ) { DWORD readLen = keyLen; err = RegEnumValue( m_hkey, t, ptr, &readLen, NULL, NULL, NULL, NULL ); if ( err == ERROR_SUCCESS ) { nameList.push_back( ptr ); } } free( ptr ); } else { rval = winToMm3dError( err ); } m_error = rval; return rval; } else { return RE_NO_KEY; } } RegErrorE Mm3dRegKey::getSubKeyNames( RegStringList & nameList ) { nameList.clear(); if ( m_hkey ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; DWORD keyCount; DWORD keyLen; err = RegQueryInfoKey( m_hkey, NULL, NULL, NULL, &keyCount, &keyLen, NULL, NULL, NULL, NULL, NULL, NULL ); keyLen += 10; if ( err == ERROR_SUCCESS ) { char * ptr = (char *) malloc( keyLen ); for ( DWORD t = 0; t < keyCount; t++ ) { DWORD readLen = keyLen; err = RegEnumKeyEx( m_hkey, t, ptr, &readLen, NULL, NULL, NULL, NULL ); if ( err == ERROR_SUCCESS ) { nameList.push_back( ptr ); } } free( ptr ); } else { rval = winToMm3dError( err ); } m_error = rval; return rval; } else { return RE_NO_KEY; } } RegErrorE Mm3dRegKey::openKey( HKEY hKey, const char * subKey, RegAccessE ra ) { LONG err = ERROR_SUCCESS; RegErrorE rval = RE_NONE; switch ( ra ) { case RA_READ: err = RegOpenKeyEx( hKey, subKey, 0, KEY_READ, &m_hkey ); break; case RA_WRITE: err = RegCreateKeyEx( hKey, subKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &m_hkey, NULL ); break; default: err = RegCreateKeyEx( hKey, subKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_hkey, NULL ); break; } rval = winToMm3dError( err ); m_error = rval; return rval; } }; #endif // WIN32 mm3d-1.3.7/src/libmm3d/md2filter.cc0000644000175000017500000007217310754751776013655 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "md2filter.h" #include "texture.h" #include "texmgr.h" #include "misc.h" #include "log.h" #include "triprim.h" #include "translate.h" #include "modelstatus.h" #include "mm3dport.h" #include "datasource.h" #include "datadest.h" #include #include #include #include #include #include // FIXME this should be centralized template class FunctionCaller { public: FunctionCaller( T * obj, void (T::*method)(void) ) { m_obj = obj; m_method = method; } ~FunctionCaller() { (m_obj->*m_method)(); } private: T * m_obj; void (T::*m_method)(void); }; const unsigned MAX_QUAKE_NORMALS = 162; static float s_quakeNormals[ MAX_QUAKE_NORMALS ][3] = { #include "md2filter-anorms.h" }; #include using std::list; using std::string; static void _invertModelNormals( Model * model ) { size_t tcount = model->getTriangleCount(); for ( size_t t = 0; t < tcount; t++ ) { model->invertNormals( t ); } } static unsigned bestNormal( double * n ) { float bestDistance = 10000.0f; unsigned bestIndex = 0; float norm[3]; norm[0] = n[0]; norm[1] = n[2]; norm[2] = n[1]; for ( unsigned t = 0; t < MAX_QUAKE_NORMALS; t++ ) { float x = norm[0] - s_quakeNormals[t][0]; float y = norm[1] - s_quakeNormals[t][1]; float z = norm[2] - s_quakeNormals[t][2]; float distance = sqrt(x*x + y*y + z*z); if ( distance < bestDistance ) { bestIndex = t; bestDistance = distance; } } return bestIndex; } typedef struct _TexCoord_t { float s; float t; } TexCoordT; Md2Filter::Md2Filter() : m_lastAnimFrame( "" ), m_lastAnimIndex( -1 ) { } Md2Filter::~Md2Filter() { } Model::ModelErrorE Md2Filter::readFile( Model * model, const char * const filename ) { if ( model && filename && filename[0] ) { Model::ModelErrorE err = Model::ERROR_NONE; DataSource* src = openInput( filename, err ); FunctionCaller fc( src, &DataSource::close ); if ( err != Model::ERROR_NONE ) return err; string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); modelPath = modelPath + string("/"); model->setFilename( modelFullName.c_str() ); unsigned fileLength = src->getFileSize(); int32_t magic = 0; int32_t version = 0; int32_t skinWidth = 0; int32_t skinHeight = 0; int32_t frameSize = 0; int32_t numSkins = 0; int32_t numVertices = 0; int32_t numTexCoords = 0; int32_t numTriangles = 0; int32_t numGlCommands = 0; int32_t numFrames = 0; int32_t offsetSkins = 0; int32_t offsetTexCoords = 0; int32_t offsetTriangles = 0; int32_t offsetFrames = 0; int32_t offsetGlCommands = 0; int32_t offsetEnd = 0; src->read( magic ); src->read( version ); src->read( skinWidth ); src->read( skinHeight ); src->read( frameSize ); src->read( numSkins ); src->read( numVertices ); src->read( numTexCoords ); src->read( numTriangles ); src->read( numGlCommands ); src->read( numFrames ); src->read( offsetSkins ); src->read( offsetTexCoords ); src->read( offsetTriangles ); src->read( offsetFrames ); src->read( offsetGlCommands ); src->read( offsetEnd ); Matrix loadMatrix; loadMatrix.setRotationInDegrees( -90, -90, 0 ); if ( magic != 0x32504449 ) { return Model::ERROR_BAD_MAGIC; } if ( version != 8 ) { return Model::ERROR_UNSUPPORTED_VERSION; } log_debug( "Magic: %08X\n", (unsigned) magic ); log_debug( "Version: %d\n", version ); log_debug( "Vertices: %d\n", numVertices ); log_debug( "Faces: %d\n", numTriangles ); log_debug( "Skins: %d\n", numSkins ); log_debug( "Frames: %d\n", numFrames ); log_debug( "GL Commands: %d\n", numGlCommands ); log_debug( "Frame Size: %d\n", frameSize ); log_debug( "TexCoords: %d\n", numTexCoords ); log_debug( "Skin Width: %d\n", skinWidth ); log_debug( "Skin Height: %d\n", skinHeight ); log_debug( "Offset Skins: %d\n", offsetSkins ); log_debug( "Offset TexCoords: %d\n", offsetTexCoords ); log_debug( "Offset Triangles: %d\n", offsetTriangles ); log_debug( "Offset Frames: %d\n", offsetFrames ); log_debug( "Offset GlCommands: %d\n", offsetGlCommands ); log_debug( "Offset End: %d\n", offsetEnd ); log_debug( "File Length: %d\n", fileLength ); int32_t i; unsigned t; unsigned vertex; int animIndex = -1; m_lastAnimIndex = -1; m_animFrame = -1; m_lastAnimFrame = ""; // Read first frame to get vertices src->seek( offsetFrames ); float scale[3]; float translate[3]; char name[64]; for ( t = 0; t < 3; t++ ) src->read( scale[t] ); for ( t = 0; t < 3; t++ ) src->read( translate[t] ); //loadMatrix.apply3( scale ); //loadMatrix.apply3( translate ); src->readBytes( (uint8_t *) name, 16 ); for ( i = 0; i < numVertices; i++ ) { uint8_t coord[3]; uint8_t normal; for ( t = 0; t < 3; t++ ) { src->read( coord[t] ); } src->read( normal ); double vec[3]; vec[0] = coord[0] * scale[0] + translate[0]; vec[1] = coord[1] * scale[1] + translate[1]; vec[2] = coord[2] * scale[2] + translate[2]; loadMatrix.apply3( vec ); vertex = model->addVertex( vec[0], vec[1], vec[2] ); } // Now read all frames to get animation vertices src->seek( offsetFrames ); if ( numFrames > 1 ) { for ( int n = 0; n < numFrames; n++ ) { for ( t = 0; t < 3; t++ ) src->read( scale[t] ); for ( t = 0; t < 3; t++ ) src->read( translate[t] ); src->readBytes( (uint8_t *) name, 16 ); animIndex = addNeededAnimFrame( model, name ); for ( i = 0; i < numVertices; i++ ) { uint8_t coord[3]; uint8_t normal; for ( t = 0; t < 3; t++ ) src->read( coord[t] ); src->read( normal ); double vec[3]; vec[0] = coord[0] * scale[0] + translate[0]; vec[1] = coord[1] * scale[1] + translate[1]; vec[2] = coord[2] * scale[2] + translate[2]; loadMatrix.apply3( vec ); model->setFrameAnimVertexCoords( animIndex, m_animFrame, i, vec[0], vec[1], vec[2] ); } } } // Read texture coords so that we have them for our triangles TexCoordT * texCoordsList = new TexCoordT[ numTexCoords ]; src->seek( offsetTexCoords ); for ( i = 0; i < numTexCoords; i++ ) { int16_t s; int16_t t; src->read( s ); src->read( t ); texCoordsList[i].s = (float) s / skinWidth; texCoordsList[i].t = 1.0 - (float) t / skinHeight; } // Create group for all triangles model->addGroup( "Group" ); // Now read triangles src->seek( offsetTriangles ); for ( i = 0; i < numTriangles; i++ ) { uint16_t vertexIndices[3]; uint16_t textureIndices[3]; for ( t = 0; t < 3; t++ ) src->read( vertexIndices[t] ); unsigned tri = model->addTriangle( vertexIndices[0], vertexIndices[1], vertexIndices[2] ); model->addTriangleToGroup( 0, tri ); for ( t = 0; t < 3; t++ ) { src->read( textureIndices[t] ); model->setTextureCoords( i, t, texCoordsList[ textureIndices[t] ].s, texCoordsList[ textureIndices[t] ].t ); } } // Now read skins src->seek( offsetSkins ); TextureManager * texmgr = TextureManager::getInstance(); bool haveSkin = false; vector & modelMaterials = getMaterialList( model ); log_debug( "Skin data:\n" ); for ( i = 0; i < numSkins; i++ ) { src->readBytes( (uint8_t *) name, 64 ); log_debug( "Skin %d: %s\n", i, name ); string tempStr = name; replaceBackslash( tempStr ); char tempPath[ 64 ]; if ( !model->getMetaData( "MD2_PATH", tempPath, sizeof(tempPath) ) ) { string md2path = tempStr; size_t slashChar = md2path.rfind( '/' ); log_debug( "The '/' char is at %d\n", slashChar ); if ( slashChar < md2path.size() ) { md2path.resize( slashChar + 1 ); log_debug( "setting MD2 path to %s\n", md2path.c_str() ); model->addMetaData( "MD2_PATH", md2path.c_str() ); } } string fullName; string fullPath; string baseName; normalizePath( tempStr.c_str(), fullName, fullPath, baseName ); log_debug( "base model skin name is %s\n", baseName.c_str() ); string skin = modelPath + baseName; log_debug( "full model skin path is %s\n", skin.c_str() ); Model::Material * mat = Model::Material::get(); mat->m_name = "skin"; for ( int m = 0; m < 3; m++ ) { mat->m_ambient[m] = 0.2; mat->m_diffuse[m] = 0.8; mat->m_specular[m] = 0.0; mat->m_emissive[m] = 0.0; } mat->m_ambient[3] = 1.0; mat->m_diffuse[3] = 1.0; mat->m_specular[3] = 1.0; mat->m_emissive[3] = 1.0; mat->m_shininess = 0.0; //replaceBackslash( material->m_texture ); //replaceBackslash( material->m_alphamap ); // Get absolute path for texture string texturePath = skin; texturePath = fixAbsolutePath( modelPath.c_str(), texturePath.c_str() ); texturePath = getAbsolutePath( modelPath.c_str(), texturePath.c_str() ); mat->m_filename = texturePath; mat->m_alphaFilename = ""; if ( texmgr->getTexture( texturePath.c_str() ) ) { log_debug( "skin %d: '%s'\n", i, texturePath.c_str()); haveSkin = true; modelMaterials.push_back( mat ); } else { mat->release(); } } // If we don't have any skins, lets try to find some if ( modelMaterials.size() == 0 ) { char * noext = strdup( modelBaseName.c_str() ); char * ext = strrchr( noext, '.' ); if ( ext ) { ext[0] = '\0'; } log_debug( "no skins defined, looking for some....\n" ); list files; getFileList( files, modelPath.c_str(), noext ); list::iterator it; free( noext ); for ( it = files.begin(); it != files.end(); it++ ) { string texturePath = modelPath + (*it); texturePath = getAbsolutePath( modelPath.c_str(), texturePath.c_str() ); log_debug( "checking %s\n", texturePath.c_str() ); if ( texmgr->getTexture( texturePath.c_str() ) ) { log_debug( " %s is a skin\n", texturePath.c_str() ); haveSkin = true; Model::Material * mat = Model::Material::get(); replaceBackslash( texturePath ); mat->m_name = getFileNameFromPath( texturePath.c_str() ); for ( int m = 0; m < 3; m++ ) { mat->m_ambient[m] = 0.2; mat->m_diffuse[m] = 0.8; mat->m_specular[m] = 0.0; mat->m_emissive[m] = 0.0; } mat->m_ambient[3] = 1.0; mat->m_diffuse[3] = 1.0; mat->m_specular[3] = 1.0; mat->m_emissive[3] = 1.0; mat->m_shininess = 0.0; //replaceBackslash( material->m_texture ); //replaceBackslash( material->m_alphamap ); // Get absolute path for texture mat->m_filename = texturePath; mat->m_alphaFilename = ""; modelMaterials.push_back( mat ); } } } if ( haveSkin ) { model->setGroupTextureId( 0, 0 ); } // Now read strips/fans src->seek( offsetGlCommands ); unsigned numStrips = 0; unsigned numFans = 0; unsigned tcount = 0; for ( i = 0; i < numGlCommands; i++ ) { int32_t numVertices = 0; bool isStrip = true; uint32_t vertexIndex = 0; float u = 0.0; float v = 0.0; src->read( numVertices ); if ( numVertices != 0 ) { if ( numVertices < 0 ) { numVertices = -numVertices; isStrip = false; numFans++; } else { numStrips++; } tcount += numVertices - 2; for ( t = 0; t < (unsigned) numVertices; t++ ) { src->read( u ); src->read( v ); src->read( vertexIndex ); } } else { break; } } log_debug( "strip count: %d\n", numStrips ); log_debug( "fan count: %d\n", numFans ); log_debug( "tri count: %d\n", tcount ); delete[] texCoordsList; _invertModelNormals( model ); return Model::ERROR_NONE; } else { log_error( "no filename supplied for model filter" ); return Model::ERROR_BAD_ARGUMENT; } } // FIXME test this! Model::ModelErrorE Md2Filter::writeFile( Model * model, const char * const filename, ModelFilter::Options * o ) { if ( model && filename && filename[0] ) { { int groupTexture = -1; int gcount = model->getGroupCount(); for ( int g = 0; g < gcount; g++ ) { int tex = model->getGroupTextureId( g ); if ( tex >= 0 ) { if ( groupTexture >= 0 && groupTexture != tex ) { model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "MD2 requires all groups to have the same material." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } groupTexture = tex; } } } { unsigned tcount = model->getTriangleCount(); for ( unsigned t = 0; t < tcount; ++t ) { if ( model->getTriangleGroup( t ) < 0 ) { model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "MD2 export requires all faces to be grouped." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } } } _invertModelNormals( model ); Model::ModelErrorE err = Model::ERROR_NONE; DataDest * dst = openOutput( filename, err ); FunctionCaller fc( dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); vector & modelVertices = getVertexList( model ); vector & modelTriangles = getTriangleList( model ); vector & modelMaterials = getMaterialList( model ); unsigned numStrips = 0; unsigned numFans = 0; unsigned tcount = 0; TriPrim * tp = TriPrim::newTriPrim(); std::vector stripList; std::vector fanList; log_debug( "finding triangle primitives\n" ); if ( tp->findPrimitives( model, true ) ) { TriPrim::TriangleVertexList tvl; TriPrim::TriPrimTypeE tpt; while ( (tpt = tp->getNextPrimitive( tvl ) ) != TriPrim::TRI_PRIM_NONE ) { //log_debug( "got triangle %s with %d triangles\n", tpt == TriPrim::TRI_PRIM_STRIP ? "strip" : "fan", tvl.size() ); tcount += tvl.size() - 2; if ( tpt == TriPrim::TRI_PRIM_STRIP ) { numStrips++; stripList.push_back( tvl ); } else { numFans++; fanList.push_back( tvl ); } } numStrips = stripList.size(); numFans = fanList.size(); } delete tp; tp = NULL; log_debug( "strip count: %d\n", numStrips ); log_debug( "fan count: %d\n", numFans ); log_debug( "tri count: %d\n", tcount ); int32_t magic = 0x32504449; int32_t version = 8; int32_t skinWidth = 256; int32_t skinHeight = 256; int32_t frameSize = 0; int32_t numSkins = modelMaterials.size(); int32_t numVertices = modelVertices.size(); int32_t numTexCoords = modelTriangles.size() * 3; int32_t numTriangles = modelTriangles.size(); int32_t numGlCommands = (numTriangles + numStrips * 2 + numFans * 2) * 3 + numStrips + numFans + 1; int32_t numFrames = 0; int32_t offsetSkins = 68; int32_t offsetTexCoords = 68; int32_t offsetTriangles = 0; int32_t offsetFrames = 0; int32_t offsetGlCommands = 0; int32_t offsetEnd = 0; // Use the load matrix and then invert it Matrix saveMatrix; saveMatrix.setRotationInDegrees( -90, -90, 0 ); saveMatrix = saveMatrix.getInverse(); bool noAnim = false; frameSize = (4 * numVertices) + 40; unsigned i; unsigned animCount = model->getAnimCount( Model::ANIMMODE_FRAME ); for ( i = 0; i < animCount; i++ ) { numFrames += model->getAnimFrameCount( Model::ANIMMODE_FRAME, i ); } if ( numFrames == 0 ) { numFrames = 1; noAnim = true; } if ( ! modelMaterials.empty() && modelMaterials[0]->m_textureData ) { skinWidth = modelMaterials[0]->m_textureData->m_width; skinHeight = modelMaterials[0]->m_textureData->m_height; } // Write header dst->write(magic); dst->write(version); dst->write(skinWidth); dst->write(skinHeight); dst->write(frameSize); dst->write(numSkins); dst->write(numVertices); dst->write(numTexCoords); dst->write(numTriangles); dst->write(numGlCommands); dst->write(numFrames); dst->write(offsetSkins); dst->write(offsetTexCoords); dst->write(offsetTriangles); dst->write(offsetFrames); dst->write(offsetGlCommands); dst->write(offsetEnd); // Write skins offsetSkins = dst->offset(); for ( i = 0; i < (unsigned) numSkins; i++ ) { int8_t skinpath[64]; // must be 64 bytes for skin writing to work string fullName, fullPath, baseName; normalizePath( modelMaterials[i]->m_filename.c_str(), fullName, fullPath, baseName ); char * noext = strdup( modelBaseName.c_str() ); char * ext = strrchr( noext, '.' ); if ( ext ) { ext[0] = '\0'; } char md2path[64]; if ( model->getMetaData( "MD2_PATH", md2path, sizeof(md2path) ) ) { PORT_snprintf( (char *) skinpath, sizeof(skinpath), "%s%s", md2path, baseName.c_str() ); } else { // Assume player model PORT_snprintf( (char *) skinpath, sizeof(skinpath), "players/%s/%s", noext, baseName.c_str() ); } log_debug( "writing skin %s as %s\n", baseName.c_str(), skinpath ); dst->writeBytes( (uint8_t *) skinpath, sizeof(skinpath) ); free( noext ); } // Write texture coordinates // TODO might be able to optimize by finding shared texture coordinates offsetTexCoords = dst->offset(); for ( i = 0; i < (unsigned) numTriangles; i++ ) { for ( unsigned n = 0; n < 3; n++ ) { float sd; float td; uint16_t si; uint16_t ti; model->getTextureCoords( i, n, sd, td ); td = 1.0 - td; si = (int16_t) (sd * (double) skinWidth); dst->write(si); ti = (int16_t) (td * (double) skinHeight); dst->write(ti); } } // Write Triangles offsetTriangles = dst->offset(); for ( i = 0; i < (unsigned) numTriangles; i++ ) { for ( unsigned v = 0; v < 3; v++ ) { uint16_t vertex = (uint16_t) model->getTriangleVertex( i, v ); dst->write(vertex); } for ( unsigned v = 0; v < 3; v++ ) { uint16_t texindex = (uint16_t) i * 3 + v; dst->write(texindex); } } // Write Frames offsetFrames = dst->offset(); for ( unsigned anim = 0; (noAnim && anim == 0) || anim < model->getAnimCount( Model::ANIMMODE_FRAME ); anim++ ) { // Heh... oops model->calculateFrameNormals( anim ); std::string animname = noAnim ? "Frame" : model->getAnimName( Model::ANIMMODE_FRAME, anim ); // Check for animation name ending with a number size_t len = strlen( animname.c_str() ); log_debug( "last char of animname is '%c'\n", animname[len-1] ); if ( len > 0 && isdigit( animname[len-1] ) ) { log_debug( "appending underscore\n" ); // last char is number, append an underscore as a separator animname += '_'; } for ( unsigned i = 0; (noAnim && i == 0) || i < model->getAnimFrameCount( Model::ANIMMODE_FRAME, anim ); i++ ) { double x0 = 0, x1 = 0; double y0 = 0, y1 = 0; double z0 = 0, z1 = 0; model->getFrameAnimVertexCoords( anim, i, 0, x0, y0, z0 ); x1 = x0; y1 = y0; z1 = z0; unsigned v; for ( v = 0; v < (unsigned) numVertices; v++ ) { double x = 0; double y = 0; double z = 0; model->getFrameAnimVertexCoords( anim, i, v, x, y, z ); if ( x < x0 ) x0 = x; if ( y < y0 ) y0 = y; if ( z < z0 ) z0 = z; if ( x > x1 ) x1 = x; if ( y > y1 ) y1 = y; if ( z > z1 ) z1 = z; } float scale[3]; float translate[3]; scale[0] = (x1 - x0) / 255.0; scale[1] = (y1 - y0) / 255.0; scale[2] = (z1 - z0) / 255.0; translate[0] = (float) (0 - (-x0)); translate[1] = (float) (0 - (-y0)); translate[2] = (float) (0 - (-z0)); saveMatrix.apply3( scale ); saveMatrix.apply3( translate ); dst->write(scale[0]); dst->write(scale[1]); dst->write(scale[2]); dst->write(translate[0]); dst->write(translate[1]); dst->write(translate[2]); char namestr[16]; snprintf( namestr, 16, "%s%03d", animname.c_str(), i ); namestr[15] = '\0'; dst->writeBytes( (uint8_t *) namestr, sizeof(namestr) ); double vertNormal[3] = {0,0,0}; for ( v = 0; v < (unsigned) numVertices; v++ ) { double vec[3] = {0, 0, 0}; model->getFrameAnimVertexCoords( anim, i, v, vec[0], vec[1], vec[2] ); saveMatrix.apply3( vec ); uint8_t xi = (uint8_t) ((vec[0] - translate[0]) / scale[0] + 0.5); uint8_t yi = (uint8_t) ((vec[1] - translate[1]) / scale[1] + 0.5); uint8_t zi = (uint8_t) ((vec[2] - translate[2]) / scale[2] + 0.5); uint8_t normal = 0; model->getFrameAnimVertexNormal( anim, i, v, vertNormal[0], vertNormal[1], vertNormal[2] ); saveMatrix.apply3( vertNormal ); // Have to invert normal vertNormal[0] = -vertNormal[0]; vertNormal[1] = -vertNormal[1]; vertNormal[2] = -vertNormal[2]; normal = bestNormal( vertNormal ); dst->write( xi ); dst->write( yi ); dst->write( zi ); dst->write( normal ); } } } // Write GL Commands offsetGlCommands = dst->offset(); if ( numTriangles > 0 ) { if ( numStrips > 0 || numFans > 0 ) { unsigned t = 0; for ( t = 0; t < numStrips; t++ ) { int32_t count = stripList[t].size(); dst->write(count); for ( unsigned i = 0; i < (unsigned) count; i++ ) { uint32_t v1 = stripList[t][i].vert; float s1 = stripList[t][i].s; float t1 = 1.0f - stripList[t][i].t; // FIXME this is reversed from below. Is it correct? dst->write(t1); dst->write(s1); dst->write(v1); } } for ( t = 0; t < numFans; t++ ) { int32_t count = fanList[t].size(); dst->write((int32_t) -count); for ( unsigned i = 0; i < (unsigned) count; i++ ) { uint32_t v1 = fanList[t][i].vert; float s1 = fanList[t][i].s; float t1 = 1.0f - fanList[t][i].t; // FIXME this is reversed from above. Is it correct? dst->write(v1); dst->write(s1); dst->write(t1); } } } } // Write GL command end marker int32_t end = 0; dst->write( end ); // Get file length offsetEnd = dst->offset(); // Re-write header dst->seek( 0 ); dst->write(magic); dst->write(version); dst->write(skinWidth); dst->write(skinHeight); dst->write(frameSize); dst->write(numSkins); dst->write(numVertices); dst->write(numTexCoords); dst->write(numTriangles); dst->write(numGlCommands); dst->write(numFrames); dst->write(offsetSkins); dst->write(offsetTexCoords); dst->write(offsetTriangles); dst->write(offsetFrames); dst->write(offsetGlCommands); dst->write(offsetEnd); _invertModelNormals( model ); model->operationComplete( "Invert normals for save" ); return Model::ERROR_NONE; } else { log_error( "no filename supplied for model filter" ); return Model::ERROR_BAD_ARGUMENT; } } bool Md2Filter::isSupported( const char * filename ) { if ( filename ) { unsigned len = strlen( filename ); if ( len >= 4 && strcasecmp( &filename[len-4], ".md2" ) == 0 ) { return true; } } return false; } list Md2Filter::getReadTypes() { list rval; rval.push_back( "*.md2" ); return rval; } list Md2Filter::getWriteTypes() { list rval; rval.push_back( "*.md2" ); return rval; } int Md2Filter::addNeededAnimFrame( Model * model, const char * name ) { char * temp = strdup( name ); int t = strlen(temp) - 1; for ( ; t > 0 && isdigit(temp[t]); t-- ) { temp[t] = '\0'; } if ( t > 0 && temp[t] == '_' ) { temp[t] = '\0'; } if ( m_lastAnimIndex == -1 || strcasecmp( temp, m_lastAnimFrame.c_str() ) != 0 ) { m_lastAnimFrame = temp; m_lastAnimIndex = model->addAnimation( Model::ANIMMODE_FRAME, temp ); model->setAnimFPS( Model::ANIMMODE_FRAME, m_lastAnimIndex, 10.0 ); m_animFrame = 0; } else { m_animFrame++; } model->setAnimFrameCount( Model::ANIMMODE_FRAME, m_lastAnimIndex, m_animFrame+1 ); free( temp ); return m_lastAnimIndex; } mm3d-1.3.7/src/libmm3d/undo.h0000644000175000017500000000227710744511346012554 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __UNDO_H #define __UNDO_H class Undo { public: Undo(); virtual bool combine( Undo * u ) = 0; virtual void undoRelease() {}; virtual void redoRelease() {}; virtual void release() { delete this; }; virtual unsigned size() { return sizeof(Undo); }; protected: virtual ~Undo(); }; #endif // __UNDO_H mm3d-1.3.7/src/libmm3d/mm3dfilter.h0000644000175000017500000000456210744511346013654 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __MM3DFILTER_H #define __MM3DFILTER_H #include "modelfilter.h" #include "local_ptr.h" #include "datasource.h" #include "datadest.h" #include class MisfitFilter : public ModelFilter { public: MisfitFilter(); virtual ~MisfitFilter(); Model::ModelErrorE readFile( Model * model, const char * const filename ); Model::ModelErrorE writeFile( Model * model, const char * const filename, ModelFilter::Options * o = NULL ); bool canRead( const char * filename ); bool canWrite( const char * filename ); bool canExport( const char * filename ); bool isSupported( const char * filename ); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); static const char MAGIC[]; static const uint8_t WRITE_VERSION_MAJOR; static const uint8_t WRITE_VERSION_MINOR; static const uint16_t OFFSET_TYPE_MASK; static const uint16_t OFFSET_UNI_MASK; static const uint16_t OFFSET_DIRTY_MASK; protected: void read( float32_t & val ); void write( float32_t val ); void writeBytes( const void * buf, size_t len ); void writeHeaderA( uint16_t flags, uint32_t count ); void writeHeaderB( uint16_t flags, uint32_t count, uint32_t size ); void readHeaderA( uint16_t & flags, uint32_t & count ); void readHeaderB( uint16_t & flags, uint32_t & count, uint32_t & size ); DataSource * m_src; DataDest * m_dst; size_t m_readLength; }; #endif // __MM3DFILTER_H mm3d-1.3.7/src/libmm3d/filefactory.h0000644000175000017500000000365610745042274014120 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef FILEFACTORY_H_INC__ #define FILEFACTORY_H_INC__ // The FileFactory creates DataSource and DataDest objects. It is used by // the ModelFilter class so that file I/O can be replaced with memory I/O. // // To implement a different FileFactory type, override createDest and // createSource to create the DataDest and DataSource types of your choice. #include #include class DataDest; class DataSource; class FileFactory { public: typedef std::map< std::string, DataDest * > DestMap; typedef std::map< std::string, DataSource * > SourceMap; FileFactory(); virtual ~FileFactory(); void closeAll(); DataDest * getDest( const char * filename ); DataSource * getSource( const char * filename ); SourceMap & getSourceMap() { return m_sources; } DestMap & getDestMap() { return m_dests; } protected: virtual DataDest * createDest( const char * filename ); virtual DataSource * createSource( const char * filename ); private: DestMap m_dests; SourceMap m_sources; }; #endif // FILEFACTORY_H_INC__ mm3d-1.3.7/src/libmm3d/filtermgr.cc0000644000175000017500000001515311000471707013725 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include // For NULL #include "filtermgr.h" #include "modelfilter.h" #include "log.h" #include using std::list; using std::string; FilterManager * FilterManager::s_instance = NULL; FilterManager::FilterManager() { } FilterManager::~FilterManager() { log_debug( "FilterManager releasing %d filters\n", m_filters.size() ); FilterList::iterator it = m_filters.begin(); while ( it != m_filters.end() ) { if ( *it ) { (*it)->release(); } it++; } } FilterManager * FilterManager::getInstance() { if ( !s_instance ) { s_instance = new FilterManager(); } return s_instance; } void FilterManager::release() { if ( s_instance != NULL ) { delete s_instance; s_instance = NULL; } } bool FilterManager::registerFilter( ModelFilter * filter ) { if ( filter ) { filter->setFactory( &m_factory ); m_filters.push_back( filter ); return true; } else { return false; } } Model::ModelErrorE FilterManager::readFile( Model * model, const char * filename ) { Model::ModelErrorE rval = Model::ERROR_UNKNOWN_TYPE; FilterList::iterator it; for ( it = m_filters.begin(); it != m_filters.end(); it++ ) { ModelFilter * filter = *it; if ( filter && filter->isSupported( filename ) ) { if ( filter->canRead() ) { model->setUndoEnabled( false ); model->forceAddOrDelete( true ); rval = filter->readFile( model, filename ); model->forceAddOrDelete( false ); model->setUndoEnabled( true ); model->clearUndo(); m_factory.closeAll(); return rval; } else { rval = Model::ERROR_UNSUPPORTED_OPERATION; } } } return rval; } Model::ModelErrorE FilterManager::writeFile( Model * model, const char * filename, bool exportModel, FilterManager::WriteOptionsE wo ) { bool canWrite = true; bool tryExport = false; FilterList::iterator it; for ( it = m_filters.begin(); it != m_filters.end(); it++ ) { ModelFilter * filter = *it; if ( filter && filter->isSupported( filename ) ) { if ( (exportModel && filter->canExport()) || filter->canWrite() ) { bool mustFree = false; ModelFilter::OptionsFuncF f = filter->getOptionsPrompt(); ModelFilter::Options * o = NULL; switch ( wo ) { case WO_FilterDefault: o = filter->getDefaultOptions(); mustFree = true; break; case WO_ModelDefault: case WO_ModelNoPrompt: //o = model->getWriteOptions( filename ); if ( o == NULL ) { o = filter->getDefaultOptions(); mustFree = true; } break; default: break; } bool doWrite = true; if ( f != NULL && o != NULL && wo != WO_ModelNoPrompt ) { doWrite = f( model, o ); } Model::ModelErrorE err = Model::ERROR_NONE; if ( doWrite ) { err = filter->writeFile( model, filename, o ); m_factory.closeAll(); } else { err = Model::ERROR_CANCEL; } if ( mustFree ) { if ( o ) { o->release(); } o = NULL; } return err; } else { if ( !exportModel && filter->canExport() ) { tryExport = true; } else { canWrite = false; } } } } if ( tryExport ) { return Model::ERROR_EXPORT_ONLY; } if ( canWrite ) { return Model::ERROR_UNKNOWN_TYPE; } else { return Model::ERROR_UNSUPPORTED_OPERATION; } } list FilterManager::getAllReadTypes() { list rval; FilterList::iterator filterIt = m_filters.begin(); while ( filterIt != m_filters.end() ) { list temp = (*filterIt)->getReadTypes(); while ( temp.size() ) { // Add to read list if we can read a dummy file of this type string tempFile = string( "file." ) + temp.front(); if ( (*filterIt)->canRead( tempFile.c_str() ) ) { string s = temp.front(); rval.push_back( s ); #ifndef WIN32 unsigned len = s.length(); for ( unsigned n = 0; n < len; n++ ) { if ( isupper( s[n] ) ) { s[n] = tolower( s[n] ); } else { s[n] = toupper( s[n] ); } } rval.push_back( s ); #endif // ! WIN32 } temp.pop_front(); } filterIt++; } return rval; } list FilterManager::getAllWriteTypes( bool exportModel ) { list rval; FilterList::iterator filterIt = m_filters.begin(); while ( filterIt != m_filters.end() ) { list temp = (*filterIt)->getWriteTypes(); while ( temp.size() ) { // Add to write list if we can write a dummy file of this type string tempFile = string( "file." ) + temp.front(); if ( (exportModel && (*filterIt)->canExport( tempFile.c_str() )) || (*filterIt)->canWrite( tempFile.c_str() ) ) { rval.push_back( temp.front() ); } temp.pop_front(); } filterIt++; } return rval; } mm3d-1.3.7/src/libmm3d/log.h0000644000175000017500000000461410744511346012365 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __LOG_H #define __LOG_H #ifdef __DO_PROFILE #include #include extern FILE * _logProfileFP; class LogProfileObject { public: inline LogProfileObject( const char * str ) // str will *NOT* be copied! : m_str( str ) { if ( _logProfileFP ) { ftime( &m_startTb ); fprintf( _logProfileFP, "IN: %d.%03d %s\n", (int) m_startTb.time, m_startTb.millitm, str ); } } inline ~LogProfileObject() { if ( _logProfileFP ) { struct timeb tb; ftime( &tb ); fprintf( _logProfileFP, "OUT: %d.%03d (%d) %s\n", (int) tb.time, tb.millitm, ((int)tb.time * 1000 + tb.millitm) - ((int)m_startTb.time * 1000 + m_startTb.millitm), m_str ); } } private: struct timeb m_startTb; const char * m_str; }; extern void log_profile_init( const char * filename ); extern void log_profile_shutdown(); #define LOG_PROFILE() LogProfileObject _profileObj( __PRETTY_FUNCTION__ ); #define LOG_PROFILE_STR(x) LogProfileObject _profileObj( (x) ); #else #define LOG_PROFILE() #define LOG_PROFILE_STR(x) #define log_profile_init(x) #define log_profile_shutdown() #endif // __DO_PROFILE extern void log_enable_debug( bool o ); extern void log_enable_warning( bool o ); extern void log_enable_error( bool o ); extern void log_debug( const char * fmt, ... ); extern void log_warning( const char * fmt, ... ); extern void log_error( const char * fmt, ... ); #endif // __LOG_H mm3d-1.3.7/src/libmm3d/model_draw.cc0000644000175000017500000015642211031447761014063 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "model.h" #include "log.h" #include "texture.h" #include static void _defaultMaterial() { float fval[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; glMaterialfv( GL_FRONT, GL_AMBIENT, fval ); fval[0] = fval[1] = fval[2] = 0.8f; glMaterialfv( GL_FRONT, GL_DIFFUSE, fval ); fval[0] = fval[1] = fval[2] = 0.0f; glMaterialfv( GL_FRONT, GL_SPECULAR, fval ); glMaterialfv( GL_FRONT, GL_EMISSION, fval ); glMaterialf( GL_FRONT, GL_SHININESS, 0.0f ); } static void _drawPointOrientation( bool selected, float scale, const Matrix & m ) { float color = (selected) ? 0.9f : 0.7f; Vector v1; Vector v2; glBegin( GL_LINES ); glColor3f( color, 0.0f, 0.0f ); v1.setAll( 0.0, 0.0, 0.0 ); v2.setAll( scale, 0.0, scale ); v1.transform( m ); v2.transform( m ); glVertex3dv( v1.getVector() ); glVertex3dv( v2.getVector() ); v1.setAll( scale, 0.0, scale ); v2.setAll( 0.0, 0.0, scale * 2 ); v1.transform( m ); v2.transform( m ); glVertex3dv( v1.getVector() ); glVertex3dv( v2.getVector() ); glColor3f( 0.0f, color, 0.0f ); v1.setAll( 0.0, 0.0, 0.0 ); v2.setAll( 0.0, scale, scale ); v1.transform( m ); v2.transform( m ); glVertex3dv( v1.getVector() ); glVertex3dv( v2.getVector() ); v1.transform( m ); v2.transform( m ); v1.setAll( 0.0, scale, scale ); v2.setAll( 0.0, 0.0, scale * 2 ); v1.transform( m ); v2.transform( m ); glVertex3dv( v1.getVector() ); glVertex3dv( v2.getVector() ); glColor3f( 0.0f, 0.0f, color ); v1.setAll( 0.0, 0.0, 0.0 ); v2.setAll( 0.0, 0.0, scale * 3 ); v1.transform( m ); v2.transform( m ); glVertex3dv( v1.getVector() ); glVertex3dv( v2.getVector() ); glEnd(); // GL_LINES } static void _drawPointOrientation( bool selected, float scale, const double * trans, const double * rot ) { Matrix m; m.setTranslation( trans ); m.setRotation( rot ); _drawPointOrientation( selected, scale, m ); } static const int CYL_VERT_COUNT = 8; static const int CYL_SEAM_VERT = 2; static double _cylinderVertices[ CYL_VERT_COUNT ][ 3 ] = { { 0.30, 1.00, 0.00 }, { 0.21, 1.00, 0.21 }, { 0.00, 1.00, 0.30 }, { -0.21, 1.00, 0.21 }, { -0.30, 1.00, 0.00 }, { -0.21, 1.00, -0.21 }, { 0.00, 1.00, -0.30 }, { 0.21, 1.00, -0.21 }, }; static void _drawProjectionCylinder( bool selected, float scale, const Vector & pos, const Vector & up, const Vector & seam ) { float color = (selected) ? 0.75f : 0.55f; double topVerts[ CYL_VERT_COUNT ][ 3 ]; double botVerts[ CYL_VERT_COUNT ][ 3 ]; int i; int v; double left[3] = {0,0,0}; double orig[3] = {0,0,0}; calculate_normal( left, orig, (double *) up.getVector(), (double *) seam.getVector() ); double len = mag3( up.getVector() ); Vector seamVec = seam; seamVec.normalize3(); seamVec.scale( len ); for ( i = 0; i < 3; i++ ) { left[i] *= len; } Matrix m; for ( i = 0; i < 3; i++ ) { m.set( 0, i, left[i] ); m.set( 1, i, up.get(i) ); m.set( 2, i, seamVec.get(i) ); } for ( v = 0; v < CYL_VERT_COUNT; v++ ) { topVerts[ v ][ 0 ] = _cylinderVertices[ v ][ 0 ]; topVerts[ v ][ 1 ] = _cylinderVertices[ v ][ 1 ]; topVerts[ v ][ 2 ] = _cylinderVertices[ v ][ 2 ]; botVerts[ v ][ 0 ] = _cylinderVertices[ v ][ 0 ]; botVerts[ v ][ 1 ] = -_cylinderVertices[ v ][ 1 ]; botVerts[ v ][ 2 ] = _cylinderVertices[ v ][ 2 ]; m.apply( topVerts[ v ] ); m.apply( botVerts[ v ] ); topVerts[v][ 0 ] += pos[ 0 ]; topVerts[v][ 1 ] += pos[ 1 ]; topVerts[v][ 2 ] += pos[ 2 ]; botVerts[v][ 0 ] += pos[ 0 ]; botVerts[v][ 1 ] += pos[ 1 ]; botVerts[v][ 2 ] += pos[ 2 ]; } glLineStipple( 1, 0xf1f1 ); glEnable( GL_LINE_STIPPLE ); glBegin( GL_LINES ); glColor3f( 0.0f, color, 0.0f ); for ( v = 0; v < CYL_VERT_COUNT; v++ ) { int v2 = (v + 1) % CYL_VERT_COUNT; glVertex3dv( topVerts[v] ); glVertex3dv( topVerts[v2] ); glVertex3dv( botVerts[v] ); glVertex3dv( botVerts[v2] ); if ( v == CYL_SEAM_VERT ) { glEnd(); glLineWidth( 3.0 ); glBegin( GL_LINES ); } glVertex3dv( topVerts[v] ); glVertex3dv( botVerts[v] ); if ( v == CYL_SEAM_VERT ) { glEnd(); glLineWidth( 1.0 ); glBegin( GL_LINES ); } } glEnd(); // GL_LINES glDisable( GL_LINE_STIPPLE ); glLineWidth( 1.0 ); glBegin( GL_POINTS ); glVertex3dv( topVerts[ CYL_SEAM_VERT ] ); glVertex3dv( botVerts[ CYL_SEAM_VERT ] ); glEnd(); } static const int SPH_VERT_COUNT = 8; static const int SPH_SEAM_VERT_TOP = 0; static const int SPH_SEAM_VERT_BOT = 4; static double _sphereXVertices[ SPH_VERT_COUNT ][ 3 ] = { { 0.00, 1.00, 0.00 }, { 0.00, 0.71, 0.71 }, { 0.00, 0.00, 1.00 }, { 0.00, -0.71, 0.71 }, { 0.00, -1.00, 0.00 }, { 0.00, -0.71, -0.71 }, { 0.00, 0.00, -1.00 }, { 0.00, 0.71, -0.71 }, }; static double _sphereYVertices[ SPH_VERT_COUNT ][ 3 ] = { { 1.00, 0.00, 0.00 }, { 0.71, 0.00, 0.71 }, { 0.00, 0.00, 1.00 }, { -0.71, 0.00, 0.71 }, { -1.00, 0.00, 0.00 }, { -0.71, 0.00, -0.71 }, { 0.00, 0.00, -1.00 }, { 0.71, 0.00, -0.71 }, }; static double _sphereZVertices[ SPH_VERT_COUNT ][ 3 ] = { { 1.00, 0.00, 0.00 }, { 0.71, 0.71, 0.00 }, { 0.00, 1.00, 0.00 }, { -0.71, 0.71, 0.00 }, { -1.00, 0.00, 0.00 }, { -0.71, -0.71, 0.00 }, { 0.00, -1.00, 0.00 }, { 0.71, -0.71, 0.00 }, }; static void _drawProjectionSphere( bool selected, float scale, const Vector & pos, const Vector & up, const Vector & seam ) { float color = (selected) ? 0.75f : 0.55f; double xVerts[ SPH_VERT_COUNT ][ 3 ]; double yVerts[ SPH_VERT_COUNT ][ 3 ]; double zVerts[ SPH_VERT_COUNT ][ 3 ]; int i; int v; double left[3] = {0,0,0}; double orig[3] = {0,0,0}; calculate_normal( left, orig, (double *) up.getVector(), (double *) seam.getVector() ); Vector seamVec = seam; seamVec.normalize3(); double len = mag3( (double *) up.getVector() ); seamVec.scale( len ); for ( i = 0; i < 3; i++ ) { left[i] *= len; } Matrix m; for ( i = 0; i < 3; i++ ) { m.set( 0, i, left[i] ); m.set( 1, i, up.get(i) ); m.set( 2, i, seamVec.get(i) ); } for ( v = 0; v < SPH_VERT_COUNT; v++ ) { xVerts[ v ][ 0 ] = _sphereXVertices[ v ][ 0 ]; xVerts[ v ][ 1 ] = _sphereXVertices[ v ][ 1 ]; xVerts[ v ][ 2 ] = _sphereXVertices[ v ][ 2 ]; yVerts[ v ][ 0 ] = _sphereYVertices[ v ][ 0 ]; yVerts[ v ][ 1 ] = _sphereYVertices[ v ][ 1 ]; yVerts[ v ][ 2 ] = _sphereYVertices[ v ][ 2 ]; zVerts[ v ][ 0 ] = _sphereZVertices[ v ][ 0 ]; zVerts[ v ][ 1 ] = _sphereZVertices[ v ][ 1 ]; zVerts[ v ][ 2 ] = _sphereZVertices[ v ][ 2 ]; m.apply( xVerts[ v ] ); m.apply( yVerts[ v ] ); m.apply( zVerts[ v ] ); xVerts[v][ 0 ] += pos[ 0 ]; xVerts[v][ 1 ] += pos[ 1 ]; xVerts[v][ 2 ] += pos[ 2 ]; yVerts[v][ 0 ] += pos[ 0 ]; yVerts[v][ 1 ] += pos[ 1 ]; yVerts[v][ 2 ] += pos[ 2 ]; zVerts[v][ 0 ] += pos[ 0 ]; zVerts[v][ 1 ] += pos[ 1 ]; zVerts[v][ 2 ] += pos[ 2 ]; } glLineStipple( 1, 0xf1f1 ); glEnable( GL_LINE_STIPPLE ); glBegin( GL_LINES ); glColor3f( 0.0f, color, 0.0f ); bool thick = false; for ( v = 0; v < SPH_VERT_COUNT; v++ ) { int v2 = (v + 1) % SPH_VERT_COUNT; if ( v >= SPH_SEAM_VERT_TOP && v < SPH_SEAM_VERT_BOT ) { glEnd(); glLineWidth( 3.0 ); glBegin( GL_LINES ); thick = true; } glVertex3dv( xVerts[v] ); glVertex3dv( xVerts[v2] ); if ( thick ) { glEnd(); glLineWidth( 1.0 ); glBegin( GL_LINES ); thick = false; } glVertex3dv( yVerts[v] ); glVertex3dv( yVerts[v2] ); glVertex3dv( zVerts[v] ); glVertex3dv( zVerts[v2] ); } glEnd(); // GL_LINES glDisable( GL_LINE_STIPPLE ); glBegin( GL_POINTS ); glVertex3dv( xVerts[ SPH_SEAM_VERT_TOP ] ); glVertex3dv( xVerts[ SPH_SEAM_VERT_BOT ] ); glEnd(); } static const int PLN_VERT_COUNT = 4; static double _planeVertices[ PLN_VERT_COUNT ][ 3 ] = { { -1.00, -1.00, 0.00 }, { 1.00, -1.00, 0.00 }, { 1.00, 1.00, 0.00 }, { -1.00, 1.00, 0.00 }, }; static void _drawProjectionPlane( bool selected, float scale, const Vector & pos, const Vector & up, const Vector & seam ) { float color = (selected) ? 0.75f : 0.55f; double verts[ PLN_VERT_COUNT ][ 3 ]; int i; int v; double left[3] = {0,0,0}; double orig[3] = {0,0,0}; calculate_normal( left, orig, (double *) up.getVector(), (double *) seam.getVector() ); Vector seamVec = seam; seamVec.normalize3(); double len = mag3( (double *) up.getVector() ); seamVec.scale( len ); for ( i = 0; i < 3; i++ ) { left[i] *= len; } Matrix m; for ( i = 0; i < 3; i++ ) { m.set( 0, i, left[i] ); m.set( 1, i, up.get(i) ); m.set( 2, i, seamVec.get(i) ); } for ( v = 0; v < PLN_VERT_COUNT; v++ ) { verts[ v ][ 0 ] = _planeVertices[ v ][ 0 ]; verts[ v ][ 1 ] = _planeVertices[ v ][ 1 ]; verts[ v ][ 2 ] = _planeVertices[ v ][ 2 ]; m.apply( verts[ v ] ); verts[v][ 0 ] += pos[ 0 ]; verts[v][ 1 ] += pos[ 1 ]; verts[v][ 2 ] += pos[ 2 ]; } glLineStipple( 1, 0xf1f1 ); glLineWidth( 3.0 ); glEnable( GL_LINE_STIPPLE ); glBegin( GL_LINES ); glColor3f( 0.0f, color, 0.0f ); for ( v = 0; v < PLN_VERT_COUNT; v++ ) { int v2 = (v + 1) % PLN_VERT_COUNT; glVertex3dv( verts[v] ); glVertex3dv( verts[v2] ); } glEnd(); // GL_LINES glDisable( GL_LINE_STIPPLE ); glLineWidth( 1.0 ); } void Model::draw( unsigned drawOptions, ContextT context, float * viewPoint ) { bool colorSelected = false; if ( m_initialized ) { if ( drawOptions & DO_WIREFRAME ) { glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); } else { #ifdef MM3D_EDIT if ( drawOptions & DO_BACKFACECULL ) { glEnable( GL_CULL_FACE ); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); } else { glDisable( GL_CULL_FACE ); glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); } #else glPolygonMode( GL_FRONT, GL_FILL ); #endif } if ( !m_validNormals ) { calculateNormals(); } DrawingContext * drawContext = NULL; if ( context ) { drawContext = getDrawingContext( context ); //drawContext->m_textures.clear(); if ( !drawContext->m_valid ) { loadTextures( context ); log_debug( "loaded textures for %p\n", context ); } } if ( drawOptions & DO_ALPHA ) { glEnable( GL_BLEND ); if ( !m_validBspTree ) { calculateBspTree(); } } else { glDisable( GL_BLEND ); } for ( unsigned t = 0; t < m_triangles.size(); t++ ) { m_triangles[t]->m_marked = false; } glEnable( GL_LIGHT0 ); glDisable( GL_LIGHT1 ); _defaultMaterial(); glColor3f( 0.9f, 0.9f, 0.9f ); if ( m_animationMode ) { glDisable( GL_BLEND ); // TODO: alpha blending on animations is not implemented if ( m_animationMode == ANIMMODE_SKELETAL && m_currentAnim < m_skelAnims.size() ) { for ( unsigned m = 0; m < m_groups.size(); m++ ) { Group * grp = m_groups[m]; if ( drawOptions & DO_TEXTURE ) { glColor3f( 1.0f, 1.0f, 1.0f ); if ( grp->m_materialIndex >= 0 ) { int index = grp->m_materialIndex; glMaterialfv( GL_FRONT, GL_AMBIENT, m_materials[ index ]->m_ambient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, m_materials[ index ]->m_diffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, m_materials[ index ]->m_specular ); glMaterialfv( GL_FRONT, GL_EMISSION, m_materials[ index ]->m_emissive ); glMaterialf( GL_FRONT, GL_SHININESS, m_materials[ index ]->m_shininess ); if ( m_materials[ index ]->m_type == Model::Material::MATTYPE_TEXTURE && (!m_materials[ index ]->m_textureData->m_isBad || (drawOptions & DO_BADTEX) ) ) { if ( drawContext ) { glBindTexture( GL_TEXTURE_2D, drawContext->m_textures[ grp->m_materialIndex ] ); } else { glBindTexture( GL_TEXTURE_2D, m_materials[ grp->m_materialIndex ]->m_texture ); } glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_materials[ grp->m_materialIndex ]->m_sClamp ? GL_CLAMP : GL_REPEAT) ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_materials[ grp->m_materialIndex ]->m_tClamp ? GL_CLAMP : GL_REPEAT) ); glEnable( GL_TEXTURE_2D ); } else { glDisable( GL_TEXTURE_2D ); } } else { _defaultMaterial(); glDisable( GL_TEXTURE_2D ); } } else { _defaultMaterial(); glDisable( GL_TEXTURE_2D ); glColor3f( 0.9f, 0.9f, 0.9f ); } colorSelected = false; glBegin( GL_TRIANGLES ); for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { unsigned triIndex = *it; Triangle * triangle = m_triangles[ triIndex ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { if ( !(drawOptions & DO_TEXTURE) ) { glColor3f( 1.0, 0.0, 0.0 ); } } colorSelected = true; } else { if ( colorSelected == true ) { if ( !(drawOptions & DO_TEXTURE) ) { glColor3f( 0.9, 0.9, 0.9 ); } } colorSelected = false; } for ( int v = 0; v < 3; v++ ) { Vertex * vertex = (m_vertices[ triangle->m_vertexIndices[v] ]); glTexCoord2f( triangle->m_s[ v ], triangle->m_t[ v ] ); if ( drawOptions & DO_SMOOTHING ) { glNormal3dv( triangle->m_normalSource[v] ); } else { glNormal3dv( triangle->m_flatSource ); } glVertex3dv( vertex->m_drawSource ); } } } glEnd(); } // draw ungrouped { _defaultMaterial(); glDisable( GL_TEXTURE_2D ); glBegin( GL_TRIANGLES ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_marked == false ) { Triangle * triangle = m_triangles[ t ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { glColor3f( 1.0, 0.0, 0.0 ); } colorSelected = true; } else { if ( colorSelected == true ) { glColor3f( 0.9, 0.9, 0.9 ); } colorSelected = false; } for ( int v = 0; v < 3; v++ ) { Vertex * vertex = (m_vertices[ triangle->m_vertexIndices[v] ]); glTexCoord2f( triangle->m_s[ v ], triangle->m_t[ v ] ); if ( drawOptions & DO_SMOOTHING ) { glNormal3dv( triangle->m_normalSource[v] ); } else { glNormal3dv( triangle->m_flatSource ); } glVertex3dv( vertex->m_drawSource ); } } } } glEnd(); } } else if ( m_animationMode == ANIMMODE_FRAME && m_currentAnim < m_frameAnims.size() ) { //log_debug( "drawing animation '%s' frame %d\n", m_frameAnims[m_currentAnim]->m_name.c_str(), m_currentFrame ); if ( m_currentFrame < m_frameAnims[m_currentAnim]->m_frameData.size() && m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices->size() > 0 ) { for ( unsigned m = 0; m < m_groups.size(); m++ ) { Group * grp = m_groups[m]; if ( drawOptions & DO_TEXTURE ) { glColor3f( 1.0, 1.0, 1.0 ); if ( grp->m_materialIndex >= 0 ) { int index = grp->m_materialIndex; glMaterialfv( GL_FRONT, GL_AMBIENT, m_materials[ index ]->m_ambient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, m_materials[ index ]->m_diffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, m_materials[ index ]->m_specular ); glMaterialfv( GL_FRONT, GL_EMISSION, m_materials[ index ]->m_emissive ); glMaterialf( GL_FRONT, GL_SHININESS, m_materials[ index ]->m_shininess ); if ( m_materials[ index ]->m_type == Model::Material::MATTYPE_TEXTURE && (!m_materials[ index ]->m_textureData->m_isBad || (drawOptions & DO_BADTEX) ) ) { if ( drawContext ) { glBindTexture( GL_TEXTURE_2D, drawContext->m_textures[ grp->m_materialIndex ] ); } else { glBindTexture( GL_TEXTURE_2D, m_materials[ grp->m_materialIndex ]->m_texture ); } glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_materials[ grp->m_materialIndex ]->m_sClamp ? GL_CLAMP : GL_REPEAT) ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_materials[ grp->m_materialIndex ]->m_tClamp ? GL_CLAMP : GL_REPEAT) ); glEnable( GL_TEXTURE_2D ); } else { glDisable( GL_TEXTURE_2D ); } } else { _defaultMaterial(); glDisable( GL_TEXTURE_2D ); } } else { _defaultMaterial(); glColor3f( 0.9, 0.9, 0.9 ); glDisable( GL_TEXTURE_2D ); } colorSelected = false; glBegin( GL_TRIANGLES ); for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { Triangle * triangle = m_triangles[ *it ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { if ( !(drawOptions & DO_TEXTURE) ) { glColor3f( 1.0, 0.0, 0.0 ); } } colorSelected = true; } else { if ( colorSelected == true ) { if ( !(drawOptions & DO_TEXTURE) ) { glColor3f( 0.9, 0.9, 0.9 ); } } colorSelected = false; } for ( int v = 0; v < 3; v++ ) { FrameAnimVertex * vertex = ((*m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices)[ triangle->m_vertexIndices[v] ]); glTexCoord2f( triangle->m_s[ v ], triangle->m_t[ v ] ); glNormal3f( vertex->m_normal[0], vertex->m_normal[1], vertex->m_normal[2] ); glVertex3f( vertex->m_coord[0], vertex->m_coord[1], vertex->m_coord[2] ); } } } glEnd(); } // draw ungrouped { _defaultMaterial(); glDisable( GL_TEXTURE_2D ); glBegin( GL_TRIANGLES ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_marked == false ) { Triangle * triangle = m_triangles[ t ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { glColor3f( 1.0, 0.0, 0.0 ); } colorSelected = true; } else { if ( colorSelected == true ) { glColor3f( 0.9, 0.9, 0.9 ); } colorSelected = false; } for ( int v = 0; v < 3; v++ ) { FrameAnimVertex * vertex = ((*m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices)[ triangle->m_vertexIndices[v] ]); glNormal3f( vertex->m_normal[0], vertex->m_normal[1], vertex->m_normal[2] ); glVertex3f( vertex->m_coord[0], vertex->m_coord[1], vertex->m_coord[2] ); } } } } glEnd(); } } else { log_error( "No frame, (or no vertices) for this animation frame.\n" ); } } } else { bool skipAlphaGroup = false; for ( unsigned m = 0; m < m_groups.size(); m++ ) { Group * grp = m_groups[m]; skipAlphaGroup = false; if ( drawOptions & DO_TEXTURE ) { glColor3f( 1.0, 1.0, 1.0 ); if ( grp->m_materialIndex >= 0 ) { int index = grp->m_materialIndex; if ( (drawOptions & DO_ALPHA) && m_materials[ index ]->m_type == Model::Material::MATTYPE_TEXTURE && m_materials[ index ]->m_textureData->m_format == Texture::FORMAT_RGBA ) { skipAlphaGroup = true; } glMaterialfv( GL_FRONT, GL_AMBIENT, m_materials[ index ]->m_ambient ); glMaterialfv( GL_FRONT, GL_DIFFUSE, m_materials[ index ]->m_diffuse ); glMaterialfv( GL_FRONT, GL_SPECULAR, m_materials[ index ]->m_specular ); glMaterialfv( GL_FRONT, GL_EMISSION, m_materials[ index ]->m_emissive ); glMaterialf( GL_FRONT, GL_SHININESS, m_materials[ index ]->m_shininess ); if ( m_materials[ index ]->m_type == Model::Material::MATTYPE_TEXTURE && (!m_materials[ index ]->m_textureData->m_isBad || (drawOptions & DO_BADTEX) ) ) { if ( drawContext ) { glBindTexture( GL_TEXTURE_2D, drawContext->m_textures[ grp->m_materialIndex ] ); } else { glBindTexture( GL_TEXTURE_2D, m_materials[ grp->m_materialIndex ]->m_texture ); } glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (m_materials[ grp->m_materialIndex ]->m_sClamp ? GL_CLAMP : GL_REPEAT) ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (m_materials[ grp->m_materialIndex ]->m_tClamp ? GL_CLAMP : GL_REPEAT) ); glEnable( GL_TEXTURE_2D ); } else { glDisable( GL_TEXTURE_2D ); } } else { _defaultMaterial(); glDisable( GL_TEXTURE_2D ); glColor3f( 0.9, 0.9, 0.9 ); } } else { _defaultMaterial(); } colorSelected = false; if ( skipAlphaGroup == false ) { glBegin( GL_TRIANGLES ); for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { Triangle * triangle = m_triangles[ *it ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { if ( !(drawOptions & DO_TEXTURE) ) { glColor3f( 1.0, 0.0, 0.0 ); } glEnd(); glDisable( GL_LIGHT0 ); glEnable( GL_LIGHT1 ); glBegin( GL_TRIANGLES ); } colorSelected = true; } else { if ( colorSelected == true ) { if ( !(drawOptions & DO_TEXTURE) ) { glColor3f( 0.9, 0.9, 0.9 ); } } glEnd(); glDisable( GL_LIGHT1 ); glEnable( GL_LIGHT0 ); glBegin( GL_TRIANGLES ); colorSelected = false; } for ( int v = 0; v < 3; v++ ) { Vertex * vertex = (m_vertices[ triangle->m_vertexIndices[v] ]); glTexCoord2f( triangle->m_s[ v ], triangle->m_t[ v ] ); if ( (drawOptions & DO_SMOOTHING) ) { glNormal3dv( triangle->m_finalNormals[v] ); } else { glNormal3dv( triangle->m_flatNormals ); } glVertex3dv( vertex->m_coord ); } } } glEnd(); } else { for ( std::set::const_iterator it = grp->m_triangleIndices.begin(); it != grp->m_triangleIndices.end(); ++it ) { m_triangles[ *it ]->m_marked = true; } } } // Draw ungrouped triangles { _defaultMaterial(); glDisable( GL_TEXTURE_2D ); glBegin( GL_TRIANGLES ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { if ( m_triangles[t]->m_marked == false ) { Triangle * triangle = m_triangles[ t ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { glColor3f( 1.0, 0.0, 0.0 ); } glEnd(); glDisable( GL_LIGHT0 ); glEnable( GL_LIGHT1 ); glBegin( GL_TRIANGLES ); colorSelected = true; } else { if ( colorSelected == true ) { glColor3f( 0.9, 0.9, 0.9 ); } glEnd(); glDisable( GL_LIGHT1 ); glEnable( GL_LIGHT0 ); glBegin( GL_TRIANGLES ); colorSelected = false; } for ( int v = 0; v < 3; v++ ) { Vertex * vertex = (m_vertices[ triangle->m_vertexIndices[v] ]); if ( drawOptions & DO_SMOOTHING ) { glNormal3f( triangle->m_vertexNormals[v][0], triangle->m_vertexNormals[v][1], triangle->m_vertexNormals[v][2] ); } else { glNormal3f( triangle->m_flatNormals[0], triangle->m_flatNormals[1], triangle->m_flatNormals[2] ); } glVertex3f( vertex->m_coord[0], vertex->m_coord[1], vertex->m_coord[2] ); } } } } glEnd(); } // Draw depth-sorted alpha blended polys last if ( (drawOptions & DO_ALPHA) && viewPoint ) { m_bspTree.render( viewPoint, drawContext ); } } glDisable( GL_TEXTURE_2D ); } } void Model::drawLines() // Used for orthographic projections { bool colorSelected = false; glDisable( GL_TEXTURE_2D ); if ( m_initialized ) { if ( m_animationMode ) { if ( m_animationMode == ANIMMODE_SKELETAL && m_currentAnim < m_skelAnims.size() ) { glBegin( GL_LINES ); glColor3f( 1.0, 1.0, 1.0 ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { Triangle * triangle = m_triangles[ t ]; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { glColor3f( 1.0, 0.0, 0.0 ); } colorSelected = true; } else { if ( colorSelected == true ) { glColor3f( 1.0, 1.0, 1.0 ); } colorSelected = false; } double vertices[3][3]; for ( int v = 0; v < 3; v++ ) { Vertex * vertex = (m_vertices[ triangle->m_vertexIndices[v] ]); vertices[v][0] = vertex->m_drawSource[0]; vertices[v][1] = vertex->m_drawSource[1]; vertices[v][2] = vertex->m_drawSource[2]; } glVertex3dv( vertices[0] ); glVertex3dv( vertices[1] ); glVertex3dv( vertices[1] ); glVertex3dv( vertices[2] ); glVertex3dv( vertices[2] ); glVertex3dv( vertices[0] ); } } glEnd(); } else if ( m_animationMode == ANIMMODE_FRAME && m_currentAnim < m_frameAnims.size() ) { //log_debug( "drawing animation '%s' frame %d\n", m_frameAnims[m_currentAnim]->m_name.c_str(), m_currentFrame ); if ( m_currentFrame < m_frameAnims[m_currentAnim]->m_frameData.size() && m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices->size() > 0 ) { glBegin( GL_LINES ); glColor3f( 1.0, 1.0, 1.0 ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { Triangle * triangle = m_triangles[ t ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { glColor3f( 1.0, 0.0, 0.0 ); } colorSelected = true; } else { if ( colorSelected == true ) { glColor3f( 1.0, 1.0, 1.0 ); } colorSelected = false; } double vertices[3][3]; for ( int v = 0; v < 3; v++ ) { FrameAnimVertex * vertex = ((*m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices)[ triangle->m_vertexIndices[v] ]); vertices[v][0] = vertex->m_coord[0]; vertices[v][1] = vertex->m_coord[1]; vertices[v][2] = vertex->m_coord[2]; } glVertex3dv( vertices[0] ); glVertex3dv( vertices[1] ); glVertex3dv( vertices[1] ); glVertex3dv( vertices[2] ); glVertex3dv( vertices[2] ); glVertex3dv( vertices[0] ); } } glEnd(); } else { log_error( "No frame, (or no vertices) for this animation frame.\n" ); } } } else { glLineWidth( 1.0 ); glBegin( GL_LINES ); glColor3f( 1.0, 1.0, 1.0 ); for ( unsigned t = 0; t < m_triangles.size(); t++ ) { Triangle * triangle = m_triangles[ t ]; triangle->m_marked = true; if ( triangle->m_visible ) { if ( triangle->m_selected ) { if ( colorSelected == false ) { glEnd(); glLineWidth( 1.6 ); glBegin( GL_LINES ); glColor3f( 1.0, 0.0, 0.0 ); } colorSelected = true; } else { if ( colorSelected == true ) { glEnd(); glLineWidth( 1.0 ); glBegin( GL_LINES ); glColor3f( 1.0, 1.0, 1.0 ); } colorSelected = false; } double vertices[3][3]; for ( int v = 0; v < 3; v++ ) { Vertex * vertex = (m_vertices[ triangle->m_vertexIndices[v] ]); vertices[v][0] = vertex->m_coord[0]; vertices[v][1] = vertex->m_coord[1]; vertices[v][2] = vertex->m_coord[2]; } glVertex3dv( vertices[0] ); glVertex3dv( vertices[1] ); glVertex3dv( vertices[1] ); glVertex3dv( vertices[2] ); glVertex3dv( vertices[2] ); glVertex3dv( vertices[0] ); } } glEnd(); } } glLineWidth( 1.0 ); } void Model::drawVertices() { if ( m_initialized ) // && m_selectionMode == SelectVertices ) { if ( m_animationMode ) { // Note, in animation mode, we don't draw vertices for // skeletal animation, only for frame animations if ( m_animationMode == ANIMMODE_FRAME && m_currentAnim < m_frameAnims.size() ) { if ( m_currentFrame < m_frameAnims[m_currentAnim]->m_frameData.size() && m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices->size() > 0 ) { glPointSize( 3.0 ); glBegin( GL_POINTS ); glColor3f( 1.0, 1.0, 1.0 ); for ( unsigned t = 0; t < m_vertices.size(); t++ ) { if ( m_vertices[t]->m_visible ) { FrameAnimVertex * vertex = (*m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices)[t]; if ( m_vertices[t]->m_selected == false ) { glVertex3f( vertex->m_coord[0], vertex->m_coord[1], vertex->m_coord[2] ); } } } glEnd(); glPointSize( 4.0 ); glBegin( GL_POINTS ); glColor3f( 1.0, 0.0, 0.0 ); for ( unsigned t = 0; t < m_vertices.size(); t++ ) { if ( m_vertices[t]->m_visible ) { FrameAnimVertex * vertex = (*m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_frameVertices)[t]; if ( m_vertices[t]->m_selected ) { glVertex3f( vertex->m_coord[0], vertex->m_coord[1], vertex->m_coord[2] ); } } } glEnd(); } } } else { glPointSize( 3.0 ); glBegin( GL_POINTS ); glColor3f( 1.0, 1.0, 1.0 ); for ( unsigned t = 0; t < m_vertices.size(); t++ ) { if ( m_vertices[t]->m_visible ) { Vertex * vertex = (m_vertices[ t ]); if ( vertex->m_selected == false ) { glVertex3f( vertex->m_coord[0], vertex->m_coord[1], vertex->m_coord[2] ); } } } glEnd(); glPointSize( 4.0 ); glBegin( GL_POINTS ); glColor3f( 1.0, 0.0, 0.0 ); for ( unsigned t = 0; t < m_vertices.size(); t++ ) { if ( m_vertices[t]->m_visible ) { Vertex * vertex = (m_vertices[ t ]); if ( vertex->m_selected ) { glVertex3f( vertex->m_coord[0], vertex->m_coord[1], vertex->m_coord[2] ); } } } glEnd(); } } } #ifdef MM3D_EDIT void Model::drawJoints() { if ( m_drawJoints != JOINTMODE_NONE ) { if ( m_initialized ) { if ( m_animationMode == ANIMMODE_NONE || m_animationMode == ANIMMODE_SKELETAL ) { glPointSize( 3.0 ); glBegin( GL_LINES ); for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_visible && m_joints[j]->m_parent >= 0 && m_joints[ m_joints[j]->m_parent ]->m_visible ) { if ( m_animationMode && parentJointSelected( j ) ) { glColor3f( 1.0, 0.0, 1.0 ); } else { glColor3f( 0.0, 0.0, 1.0 ); } Joint * joint = m_joints[ j ]; Joint * parent = m_joints[ joint->m_parent ]; Vector pvec; pvec.set( 0, parent->m_final.get(3, 0) ); pvec.set( 1, parent->m_final.get(3, 1) ); pvec.set( 2, parent->m_final.get(3, 2) ); Vector jvec; jvec.set( 0, joint->m_final.get(3, 0) ); jvec.set( 1, joint->m_final.get(3, 1) ); jvec.set( 2, joint->m_final.get(3, 2) ); glVertex3f( pvec.get( 0 ), pvec.get( 1 ), pvec.get( 2 ) ); glVertex3f( jvec.get( 0 ), jvec.get( 1 ), jvec.get( 2 ) ); Vector face( 0.0, 1.0, 0.0 ); Vector point( jvec.get(0) - pvec.get(0), jvec.get(1) - pvec.get(1), jvec.get(2) - pvec.get(2) ); double length = distance( pvec, jvec ); Quaternion qrot; qrot.setRotationToPoint( face, point ); Vector v1( 0.07, 0.10, 0.07 ); Vector v2( -0.07, 0.10, 0.07 ); Vector v3( -0.07, 0.10, -0.07 ); Vector v4( 0.07, 0.10, -0.07 ); v1 = v1 * length; v2 = v2 * length; v3 = v3 * length; v4 = v4 * length; Matrix m; m.setRotationQuaternion( qrot ); v1 = v1 * m; v2 = v2 * m; v3 = v3 * m; v4 = v4 * m; if ( m_drawJoints == JOINTMODE_BONES ) { glVertex3f( pvec.get( 0 ), pvec.get( 1 ), pvec.get( 2 )); glVertex3f( pvec.get(0) + v1.get(0), pvec.get(1) + v1.get(1), pvec.get(2) + v1.get(2) ); glVertex3f( pvec.get( 0 ), pvec.get( 1 ), pvec.get( 2 )); glVertex3f( pvec.get(0) + v2.get(0), pvec.get(1) + v2.get(1), pvec.get(2) + v2.get(2) ); glVertex3f( pvec.get( 0 ), pvec.get( 1 ), pvec.get( 2 )); glVertex3f( pvec.get(0) + v3.get(0), pvec.get(1) + v3.get(1), pvec.get(2) + v3.get(2) ); glVertex3f( pvec.get( 0 ), pvec.get( 1 ), pvec.get( 2 )); glVertex3f( pvec.get(0) + v4.get(0), pvec.get(1) + v4.get(1), pvec.get(2) + v4.get(2) ); glVertex3f( pvec.get(0) + v1.get(0), pvec.get(1) + v1.get(1), pvec.get(2) + v1.get(2) ); glVertex3f( pvec.get(0) + v2.get(0), pvec.get(1) + v2.get(1), pvec.get(2) + v2.get(2) ); glVertex3f( pvec.get(0) + v2.get(0), pvec.get(1) + v2.get(1), pvec.get(2) + v2.get(2) ); glVertex3f( pvec.get(0) + v3.get(0), pvec.get(1) + v3.get(1), pvec.get(2) + v3.get(2) ); glVertex3f( pvec.get(0) + v3.get(0), pvec.get(1) + v3.get(1), pvec.get(2) + v3.get(2) ); glVertex3f( pvec.get(0) + v4.get(0), pvec.get(1) + v4.get(1), pvec.get(2) + v4.get(2) ); glVertex3f( pvec.get(0) + v4.get(0), pvec.get(1) + v4.get(1), pvec.get(2) + v4.get(2) ); glVertex3f( pvec.get(0) + v1.get(0), pvec.get(1) + v1.get(1), pvec.get(2) + v1.get(2) ); glVertex3f( jvec.get( 0 ), jvec.get( 1 ), jvec.get( 2 )); glVertex3f( pvec.get(0) + v1.get(0), pvec.get(1) + v1.get(1), pvec.get(2) + v1.get(2) ); glVertex3f( jvec.get( 0 ), jvec.get( 1 ), jvec.get( 2 )); glVertex3f( pvec.get(0) + v2.get(0), pvec.get(1) + v2.get(1), pvec.get(2) + v2.get(2) ); glVertex3f( jvec.get( 0 ), jvec.get( 1 ), jvec.get( 2 )); glVertex3f( pvec.get(0) + v3.get(0), pvec.get(1) + v3.get(1), pvec.get(2) + v3.get(2) ); glVertex3f( jvec.get( 0 ), jvec.get( 1 ), jvec.get( 2 )); glVertex3f( pvec.get(0) + v4.get(0), pvec.get(1) + v4.get(1), pvec.get(2) + v4.get(2) ); } } } glEnd(); glBegin( GL_POINTS ); for ( unsigned j = 0; j < m_joints.size(); j++ ) { if ( m_joints[j]->m_visible ) { if ( m_joints[j]->m_selected ) { glColor3f( 1.0, 0.0, 1.0 ); } else if ( m_animationMode && hasSkelAnimKeyframe( m_currentAnim, m_currentFrame, j, true ) || m_animationMode && hasSkelAnimKeyframe( m_currentAnim, m_currentFrame, j, false ) ) { glColor3f( 0.0, 1.0, 0.0 ); } else { glColor3f( 0.0, 0.0, 1.0 ); } Joint * joint = (m_joints[ j ]); glVertex3f( joint->m_final.get(3, 0), joint->m_final.get(3, 1), joint->m_final.get(3, 2) ); } } glEnd(); } } } } void Model::drawPoints() { float scale = 2.0f; if ( m_initialized ) { switch ( m_animationMode ) { case ANIMMODE_NONE: for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_visible ) { Point * point = (m_points[ p ]); _drawPointOrientation( point->m_selected, scale, point->m_trans, point->m_rot ); if ( point->m_selected ) { glColor3f( 0.7, 1.0, 0.0 ); } else { glColor3f( 0.0, 0.5, 0.0 ); } glBegin( GL_POINTS ); glVertex3f( point->m_trans[0], point->m_trans[1], point->m_trans[2] ); glEnd(); } } break; case ANIMMODE_SKELETAL: for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_visible ) { /* Matrix mat; Point * point = (m_points[ p ]); mat.setTranslation( point->m_localTranslation ); mat.setRotation( point->m_localRotation ); int j = point->m_boneId; if ( j >= 0 ) { mat = mat * m_joints[j]->m_final; } */ Matrix mat; Point * point = (m_points[ p ]); mat.setTranslation( point->m_kfTrans ); mat.setRotation( point->m_kfRot ); _drawPointOrientation( false, scale, mat ); glColor3f( 0.0, 0.5, 0.0 ); glBegin( GL_POINTS ); glVertex3d( mat.get(3, 0), mat.get(3, 1), mat.get(3, 2) ); glEnd(); } } break; case ANIMMODE_FRAME: if ( m_currentAnim < m_frameAnims.size() && m_currentFrame < m_frameAnims[m_currentAnim ]->m_frameData.size() ) { for ( unsigned p = 0; p < m_points.size(); p++ ) { if ( m_points[p]->m_visible ) { if ( p < m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_framePoints->size() ) { FrameAnimPoint * point = ((*m_frameAnims[m_currentAnim]->m_frameData[m_currentFrame]->m_framePoints)[ p ]); _drawPointOrientation( m_points[p]->m_selected, 1.0f, point->m_trans, point->m_rot ); if ( m_points[p]->m_selected ) { glColor3f( 0.7, 1.0, 0.0 ); } else { glColor3f( 0.0, 0.5, 0.0 ); } glBegin( GL_POINTS ); glVertex3f( point->m_trans[0], point->m_trans[1], point->m_trans[2] ); glEnd(); } } } } break; default: log_error( "unknown draw mode in drawPoints()\n" ); break; } } } void Model::drawProjections() { if ( m_drawProjections ) { if ( m_initialized ) { if ( m_animationMode == ANIMMODE_NONE ) { for ( unsigned p = 0; p < m_projections.size(); p++ ) { TextureProjection * proj = (m_projections[ p ]); float scale = mag3( proj->m_upVec ); Matrix m; m.set( 0, 0, proj->m_upVec[0] ); m.set( 1, 1, proj->m_upVec[1] ); m.set( 2, 2, proj->m_upVec[2] ); m.setTranslation( proj->m_pos[0], proj->m_pos[1], proj->m_pos[2] ); switch ( proj->m_type ) { case Model::TPT_Sphere: _drawProjectionSphere( proj->m_selected, scale, Vector(proj->m_pos), Vector(proj->m_upVec), Vector(proj->m_seamVec) ); break; case Model::TPT_Cylinder: _drawProjectionCylinder( proj->m_selected, scale, Vector(proj->m_pos), Vector(proj->m_upVec), Vector(proj->m_seamVec) ); break; case Model::TPT_Plane: default: _drawProjectionPlane( proj->m_selected, scale, Vector(proj->m_pos), Vector(proj->m_upVec), Vector(proj->m_seamVec) ); break; } if ( proj->m_selected ) { glColor3f( 0.7, 1.0, 0.0 ); } else { glColor3f( 0.0, 0.5, 0.0 ); } glBegin( GL_POINTS ); glVertex3f( proj->m_pos[0], proj->m_pos[1], proj->m_pos[2] ); glEnd(); } } } } } #endif // MM3D_EDIT mm3d-1.3.7/src/libmm3d/lwofilter.h0000644000175000017500000001046210744511346013611 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __LWOFILTER_H #define __LWOFILTER_H #include "modelfilter.h" #include #include #include #include #include class LwoFilter : public ModelFilter { public: LwoFilter(); virtual ~LwoFilter(); Model::ModelErrorE readFile( Model * model, const char * const filename ); Model::ModelErrorE writeFile( Model * model, const char * const filename, ModelFilter::Options * o ); bool canRead( const char * filename ); bool canWrite( const char * filename ); bool canExport( const char * filename ); bool isSupported( const char * filename ); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); struct _PolyMap_t { unsigned polyIndex; unsigned polyCount; }; typedef struct _PolyMap_t PolyMapT; typedef struct _ClipData_t { std::string filename; } ClipDataT; typedef struct _SurfaceBlockData_t { int textureIndex; } SurfaceBlockDataT; typedef struct _VertexMapData_t { int vertex; float s; float t; } VertexMapDataT; typedef struct _DiscVertexMapData_t { int polyIndex; int vertexNumber; float s; float t; } DiscVertexMapDataT; typedef std::vector< unsigned > PolyList; typedef std::vector< unsigned > SurfaceTags; typedef std::vector< PolyList > SurfacePolys; typedef std::vector< std::string > TagList; typedef std::vector< PolyMapT > PolyMapList; typedef std::vector< ClipDataT > ClipList; typedef std::vector< float > FloatList; typedef std::vector< VertexMapDataT > VertexMapList; typedef std::vector< DiscVertexMapDataT > DiscVertexMapList; protected: bool readChunk( size_t len ); bool readVertexChunk( size_t len ); bool readPolygonChunk( size_t len ); bool readSurfaceListChunk( size_t len); bool readSurfaceDefinitionChunk( size_t len ); bool readSurfaceBlockChunk( size_t len, SurfaceBlockDataT & sbd ); bool readVertexMapChunk( size_t len ); bool readDiscVertexMapChunk( size_t len ); bool readTagChunk( size_t len ); bool readPolyTagChunk( size_t len ); bool readClipChunk( size_t len ); uint32_t readU4(); uint16_t readU2(); uint8_t readU1(); int32_t readI4(); int16_t readI2(); int8_t readI1(); float readF4(); unsigned readColor( float & r, float & g, float & b ); unsigned readVX( unsigned & ); void readID( char * ); unsigned readString( char * dest, size_t len ); unsigned readNothing( size_t len ); Model * m_model; FILE * m_fp; uint8_t * m_bufPos; uint8_t * m_fileBuf; int m_curGroup; int m_vertices; int m_faces; int m_groups; uint32_t m_lastVertexBase; uint32_t m_lastPolyBase; bool m_isLWO2; SurfacePolys m_surfacePolys; SurfaceTags m_surfaceTags; TagList m_tags; PolyMapList m_polyMaps; ClipList m_clips; FloatList m_smoothAngles; VertexMapList m_vertexMaps; DiscVertexMapList m_discVertexMaps; std::string m_modelPath; std::string m_modelBaseName; std::string m_modelFullName; }; #endif // __LWOFILTER_H mm3d-1.3.7/src/libmm3d/undo.cc0000644000175000017500000000162310744511346012704 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "undo.h" Undo::Undo() { } Undo::~Undo() { } mm3d-1.3.7/src/libmm3d/ms3dfilter.cc0000644000175000017500000012003211000471707013777 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "ms3dfilter.h" #include "weld.h" #include "misc.h" #include "log.h" #include "release_ptr.h" #include "local_array.h" #include "file_closer.h" #include "mm3dport.h" #include "util.h" #include "datadest.h" #include "datasource.h" #include #include #include #include #include #include #include using std::list; using std::string; char const Ms3dFilter::MAGIC_NUMBER[] = "MS3D000000"; template class FunctionCaller { public: FunctionCaller( T * obj, void (T::*method)(void) ) { m_obj = obj; m_method = method; } ~FunctionCaller() { (m_obj->*m_method)(); } private: T * m_obj; void (T::*m_method)(void); }; /* MS3D STRUCTURES */ // File header struct MS3DHeader { char m_ID[10]; int32_t m_version; }; // Vertex information struct MS3DVertex { uint8_t m_flags; float32_t m_vertex[3]; uint8_t m_boneId; uint8_t m_refCount; }; const size_t FILE_VERTEX_SIZE = 15; // Triangle information struct MS3DTriangle { uint16_t m_flags; uint16_t m_vertexIndices[3]; float32_t m_vertexNormals[3][3]; float32_t m_s[3]; float32_t m_t[3]; uint8_t m_smoothingGroup; uint8_t m_groupIndex; }; const size_t FILE_TRIANGLE_SIZE = 72; // Material information struct MS3DMaterial { char m_name[32]; float32_t m_ambient[4]; float32_t m_diffuse[4]; float32_t m_specular[4]; float32_t m_emissive[4]; float32_t m_shininess; // 0.0f - 128.0f float32_t m_transparency; // 0.0f - 1.0f uint8_t m_mode; // 0, 1, 2 is unused now char m_texture[128]; char m_alphamap[128]; }; const size_t FILE_MATERIAL_SIZE = 361; // Joint information struct MS3DJoint { uint8_t m_flags; char m_name[32]; char m_parentName[32]; float32_t m_rotation[3]; float32_t m_translation[3]; uint16_t m_numRotationKeyframes; uint16_t m_numTranslationKeyframes; }; const size_t FILE_JOINT_SIZE = 93; // Keyframe data struct MS3DKeyframe { float32_t m_time; float32_t m_parameter[3]; }; const size_t FILE_KEYFRAME_SIZE = 16; // flags // 1 = selected // 2 = hidden // struct _JointNameListRec_t { int m_jointIndex; std::string m_name; }; typedef struct _JointNameListRec_t JointNameListRecT; Ms3dFilter::Ms3dOptions::Ms3dOptions() : m_subVersion( 0 ), m_vertexExtra( 0xffffffff ), m_jointColor( 0xffffffff ) { } Ms3dFilter::Ms3dOptions::~Ms3dOptions() { } void Ms3dFilter::Ms3dOptions::setOptionsFromModel( Model * m ) { char value[128]; if ( m->getMetaData( "ms3d_sub_version", value, sizeof(value) ) ) { m_subVersion = atoi( value ); m_subVersion = util_clamp( m_subVersion, 0, 2 ); } else { // No sub-version defined. Use zero unless we have multiple bone joint // influences for any vertex. m_subVersion = 0; unsigned vcount = m->getVertexCount(); Model::InfluenceList il; for ( unsigned v = 0; m_subVersion == 0 && v < vcount; v++ ) { m->getVertexInfluences( v, il ); if ( il.size() > 1 ) { m_subVersion = 1; } } } if ( m->getMetaData( "ms3d_vertex_extra", value, sizeof(value) ) ) { sscanf( value, "%x", &m_vertexExtra ); } // TODO joint color //if ( m->getMetaData( "ms3d_joint_color", value, sizeof(value) ) ) //{ // sscanf( value, "%x", &m_jointColor ); //} } Model::ModelErrorE Ms3dFilter::readFile( Model * model, const char * const filename ) { if ( !model || !filename ) return Model::ERROR_BAD_ARGUMENT; string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); Model::ModelErrorE err = Model::ERROR_NONE; m_src = openInput( filename, err ); FunctionCaller fc( m_src, &DataSource::close ); if ( err != Model::ERROR_NONE ) return err; model->setFilename( modelFullName.c_str() ); vector & modelVertices = getVertexList( model ); vector & modelTriangles = getTriangleList( model ); vector & modelGroups = getGroupList( model ); vector & modelMaterials = getMaterialList( model ); vector & modelJoints = getJointList( model ); unsigned fileLength = m_src->getFileSize(); m_model = model; if ( fileLength < (sizeof( MS3DHeader ) + sizeof(uint16_t) ) ) { return Model::ERROR_UNEXPECTED_EOF; } // Check header MS3DHeader header; m_src->readBytes( (uint8_t *) header.m_ID, sizeof(header.m_ID) ); m_src->read( header.m_version ); if ( strncmp( header.m_ID, MAGIC_NUMBER, 10 ) != 0 ) { log_error( "bad magic number\n" ); return Model::ERROR_BAD_MAGIC; } int version = header.m_version; if ( version < 3 || version > 4 ) { log_error( "unsupported version\n" ); return Model::ERROR_UNSUPPORTED_VERSION; } uint16_t t; // MS Visual C++ is lame uint16_t numVertices = 0; m_src->read( numVertices ); // TODO verify file size vs. numVertices std::vector< int > vertexJoints; for ( t = 0; t < numVertices; t++ ) { MS3DVertex vertex; m_src->read( vertex.m_flags ); m_src->read( vertex.m_vertex[0] ); m_src->read( vertex.m_vertex[1] ); m_src->read( vertex.m_vertex[2] ); m_src->read( vertex.m_boneId ); m_src->read( vertex.m_refCount ); Model::Vertex * vert = Model::Vertex::get(); for ( int v = 0; v < 3; v++ ) { vert->m_coord[v] = vertex.m_vertex[ v ]; } modelVertices.push_back( vert ); vertexJoints.push_back( vertex.m_boneId ); } uint16_t numTriangles = 0; m_src->read( numTriangles ); if ( m_src->getRemaining() < (FILE_TRIANGLE_SIZE * numTriangles + sizeof( uint16_t )) ) { return Model::ERROR_UNEXPECTED_EOF; } for ( t = 0; t < numTriangles; t++ ) { Model::Triangle * curTriangle = Model::Triangle::get(); MS3DTriangle triangle; m_src->read( triangle.m_flags ); m_src->read( triangle.m_vertexIndices[0] ); m_src->read( triangle.m_vertexIndices[1] ); m_src->read( triangle.m_vertexIndices[2] ); m_src->read( triangle.m_vertexNormals[0][0] ); m_src->read( triangle.m_vertexNormals[0][1] ); m_src->read( triangle.m_vertexNormals[0][2] ); m_src->read( triangle.m_vertexNormals[1][0] ); m_src->read( triangle.m_vertexNormals[1][1] ); m_src->read( triangle.m_vertexNormals[1][2] ); m_src->read( triangle.m_vertexNormals[2][0] ); m_src->read( triangle.m_vertexNormals[2][1] ); m_src->read( triangle.m_vertexNormals[2][2] ); m_src->read( triangle.m_s[0] ); m_src->read( triangle.m_s[1] ); m_src->read( triangle.m_s[2] ); m_src->read( triangle.m_t[0] ); m_src->read( triangle.m_t[1] ); m_src->read( triangle.m_t[2] ); m_src->read( triangle.m_smoothingGroup ); m_src->read( triangle.m_groupIndex ); curTriangle->m_vertexIndices[0] = triangle.m_vertexIndices[0]; curTriangle->m_vertexIndices[1] = triangle.m_vertexIndices[1]; curTriangle->m_vertexIndices[2] = triangle.m_vertexIndices[2]; for ( int i = 0; i < 3; i++ ) { if ( curTriangle->m_vertexIndices[i] >= numVertices ) { //log_debug( "vertex: %d/%d\n", curTriangle->m_vertexIndices[i], // modelVertices.size() ); return Model::ERROR_BAD_DATA; } } for ( int i = 0; i < 3; i++ ) { // Need to invert the T coord, since milkshape seems to store it // upside-down. curTriangle->m_s[i] = triangle.m_s[i]; curTriangle->m_t[i] = 1.0 - triangle.m_t[i]; } for ( int y = 0; y < 3; y++ ) { for( int x = 0; x < 3; x++ ) { curTriangle->m_vertexNormals[y][x] = triangle.m_vertexNormals[y][x]; } } modelTriangles.push_back( curTriangle ); } uint16_t numGroups = 0; m_src->read( numGroups ); log_debug( "model says %d groups\n" ); for ( t = 0; t < numGroups; t++ ) { Model::Group * group = Model::Group::get(); modelGroups.push_back( group ); uint8_t flags = 0; m_src->read( flags ); char tempstr[32]; readString( tempstr, sizeof(tempstr) ); group->m_name = tempstr; log_debug( "group name: %s\n", modelGroups[t]->m_name.c_str() ); uint16_t numTriangles = 0; m_src->read( numTriangles ); uint16_t triIndex = 0; for ( uint16_t n = 0; n < numTriangles; n++ ) { m_src->read( triIndex ); if ( triIndex >= modelTriangles.size() ) { log_error( "TRIANGLE OUT OF RANGE %d/%d\n", triIndex, modelTriangles.size() ); return Model::ERROR_BAD_DATA; } group->m_triangleIndices.insert( triIndex ); } int8_t material = 0; m_src->read( material ); group->m_materialIndex = material; // Already added group to m_groups } uint16_t numMaterials = 0; m_src->read( numMaterials ); log_debug( "model says %d materials\n", numMaterials ); for ( t = 0; t < numGroups; t++ ) { if ( modelGroups[t]->m_materialIndex >= numMaterials ) return Model::ERROR_BAD_DATA; } for ( t = 0; t < numMaterials; t++ ) { Model::Material * mat = Model::Material::get(); MS3DMaterial material; readString( material.m_name, sizeof(material.m_name) ); m_src->read( material.m_ambient[0] ); m_src->read( material.m_ambient[1] ); m_src->read( material.m_ambient[2] ); m_src->read( material.m_ambient[3] ); m_src->read( material.m_diffuse[0] ); m_src->read( material.m_diffuse[1] ); m_src->read( material.m_diffuse[2] ); m_src->read( material.m_diffuse[3] ); m_src->read( material.m_specular[0] ); m_src->read( material.m_specular[1] ); m_src->read( material.m_specular[2] ); m_src->read( material.m_specular[3] ); m_src->read( material.m_emissive[0] ); m_src->read( material.m_emissive[1] ); m_src->read( material.m_emissive[2] ); m_src->read( material.m_emissive[3] ); m_src->read( material.m_shininess ); m_src->read( material.m_transparency ); m_src->read( material.m_mode ); readString( material.m_texture, sizeof( material.m_texture ) ); readString( material.m_alphamap, sizeof( material.m_alphamap ) ); log_debug( "material name is %s\n", material.m_name ); mat->m_name = material.m_name; mat->m_ambient[0] = material.m_ambient[0]; mat->m_ambient[1] = material.m_ambient[1]; mat->m_ambient[2] = material.m_ambient[2]; mat->m_ambient[3] = material.m_ambient[3]; mat->m_diffuse[0] = material.m_diffuse[0]; mat->m_diffuse[1] = material.m_diffuse[1]; mat->m_diffuse[2] = material.m_diffuse[2]; mat->m_diffuse[3] = material.m_diffuse[3]; mat->m_specular[0] = material.m_specular[0]; mat->m_specular[1] = material.m_specular[1]; mat->m_specular[2] = material.m_specular[2]; mat->m_specular[3] = material.m_specular[3]; mat->m_emissive[0] = material.m_emissive[0]; mat->m_emissive[1] = material.m_emissive[1]; mat->m_emissive[2] = material.m_emissive[2]; mat->m_emissive[3] = material.m_emissive[3]; mat->m_shininess = material.m_shininess; mat->m_type = Model::Material::MATTYPE_TEXTURE; if ( material.m_texture[0] == '\0' ) { mat->m_type = Model::Material::MATTYPE_BLANK; } replaceBackslash( material.m_texture ); replaceBackslash( material.m_alphamap ); // Get absolute path for texture string texturePath = material.m_texture; texturePath = fixAbsolutePath( modelPath.c_str(), texturePath.c_str() ); texturePath = getAbsolutePath( modelPath.c_str(), texturePath.c_str() ); mat->m_filename = texturePath; // Get absolute path for alpha map texturePath = material.m_alphamap; if ( texturePath.length() > 0 ) { texturePath = fixAbsolutePath( modelPath.c_str(), texturePath.c_str() ); texturePath = getAbsolutePath( modelPath.c_str(), texturePath.c_str() ); } mat->m_alphaFilename = texturePath; modelMaterials.push_back( mat ); } setModelInitialized( model, true ); float32_t fps = 0; m_src->read( fps ); // don't need this float32_t currentTime = 0; m_src->read( currentTime ); int32_t numFrames = 0; m_src->read( numFrames ); setModelNumFrames( model, numFrames ); if ( numFrames > 0 ) { model->addAnimation( Model::ANIMMODE_SKELETAL, "Keyframe" ); model->setAnimFPS( Model::ANIMMODE_SKELETAL, 0, fps ); model->setAnimFrameCount( Model::ANIMMODE_SKELETAL, 0, numFrames ); } uint16_t numJoints = 0; m_src->read( numJoints ); off_t tmpOffset = m_src->offset(); JointNameListRecT * nameList = new JointNameListRecT[ numJoints ]; local_array freeList( nameList ); for ( t = 0; t < numJoints; t++ ) { MS3DJoint joint; m_src->read( joint.m_flags ); readString( joint.m_name, sizeof( joint.m_name ) ); readString( joint.m_parentName, sizeof( joint.m_parentName ) ); m_src->read( joint.m_rotation[0] ); m_src->read( joint.m_rotation[1] ); m_src->read( joint.m_rotation[2] ); m_src->read( joint.m_translation[0] ); m_src->read( joint.m_translation[1] ); m_src->read( joint.m_translation[2] ); m_src->read( joint.m_numRotationKeyframes ); m_src->read( joint.m_numTranslationKeyframes ); m_src->seek( m_src->offset() + ( FILE_KEYFRAME_SIZE * (joint.m_numRotationKeyframes + joint.m_numTranslationKeyframes) ) ); nameList[t].m_jointIndex = t; nameList[t].m_name = joint.m_name; } m_src->seek( tmpOffset ); for ( t = 0; t < numJoints; t++ ) { log_debug( "Reading joint %d\n", t ); MS3DJoint joint; m_src->read( joint.m_flags ); readString( joint.m_name, sizeof( joint.m_name ) ); readString( joint.m_parentName, sizeof( joint.m_parentName ) ); m_src->read( joint.m_rotation[0] ); m_src->read( joint.m_rotation[1] ); m_src->read( joint.m_rotation[2] ); m_src->read( joint.m_translation[0] ); m_src->read( joint.m_translation[1] ); m_src->read( joint.m_translation[2] ); m_src->read( joint.m_numRotationKeyframes ); m_src->read( joint.m_numTranslationKeyframes ); int parentIndex = -1; if ( strlen(joint.m_parentName) > 0 ) { for ( uint16_t j = 0; j < numJoints; j++ ) { if ( strcasecmp( nameList[j].m_name.c_str(), joint.m_parentName ) == 0 ) { parentIndex = nameList[j].m_jointIndex; break; } } if ( parentIndex == -1 ) { log_error( "No parent\n" ); return Model::ERROR_BAD_DATA; // no parent! } } modelJoints.push_back( Model::Joint::get() ); for ( int i = 0; i < 3; i++ ) { modelJoints[t]->m_localRotation[i] = joint.m_rotation[i]; modelJoints[t]->m_localTranslation[i] = joint.m_translation[i]; } modelJoints[t]->m_parent = parentIndex; modelJoints[t]->m_name = joint.m_name; uint16_t numRotationKeyframes = joint.m_numRotationKeyframes; uint16_t numTranslationKeyframes = joint.m_numTranslationKeyframes; log_debug( "Joint %d keyframes: %d rot %d trans\n", t, numRotationKeyframes, numTranslationKeyframes ); uint16_t j; // MS Visual C++ is lame for ( j = 0; j < numRotationKeyframes; j++ ) { Model::Keyframe * mkeyframe = Model::Keyframe::get(); MS3DKeyframe keyframe; m_src->read( keyframe.m_time ); m_src->read( keyframe.m_parameter[0] ); m_src->read( keyframe.m_parameter[1] ); m_src->read( keyframe.m_parameter[2] ); mkeyframe->m_jointIndex = t; mkeyframe->m_time = keyframe.m_time; for ( int i = 0; i < 3; i++ ) { mkeyframe->m_parameter[i] = keyframe.m_parameter[i]; } unsigned frame = (unsigned) (keyframe.m_time / (1.0 / fps)) - 1; model->setSkelAnimKeyframe( 0, frame, t, true, mkeyframe->m_parameter[0], mkeyframe->m_parameter[1], mkeyframe->m_parameter[2] ); mkeyframe->release(); } for ( j = 0; j < numTranslationKeyframes; j++ ) { Model::Keyframe * mkeyframe = Model::Keyframe::get(); MS3DKeyframe keyframe; m_src->read( keyframe.m_time ); m_src->read( keyframe.m_parameter[0] ); m_src->read( keyframe.m_parameter[1] ); m_src->read( keyframe.m_parameter[2] ); mkeyframe->m_jointIndex = t; mkeyframe->m_time = keyframe.m_time; for ( int i = 0; i < 3; i++ ) { mkeyframe->m_parameter[i] = keyframe.m_parameter[i]; } unsigned frame = (unsigned) (keyframe.m_time / (1.0 / fps)) - 1; model->setSkelAnimKeyframe( 0, frame, t, false, mkeyframe->m_parameter[0], mkeyframe->m_parameter[1], mkeyframe->m_parameter[2] ); mkeyframe->release(); } } for ( int i = 0; i < numVertices; i++ ) { model->setVertexBoneJoint( i, vertexJoints[i] ); } bool keepReading = true; if ( !m_src->eof() ) { keepReading = readCommentSection(); } if ( keepReading && !m_src->eof() ) { keepReading = readVertexWeightSection(); } // TODO: May want to read joint extra data eventually model->setupJoints(); log_debug( "model loaded\n" ); log_debug( " vertices: %d\n", numVertices ); log_debug( " triangles: %d\n", numTriangles ); log_debug( " groups: %d\n", numGroups ); log_debug( " materials: %d\n", numMaterials ); log_debug( " joints: %d\n", numJoints ); log_debug( "\n" ); return Model::ERROR_NONE; } Model::ModelErrorE Ms3dFilter::writeFile( Model * model, const char * const filename, ModelFilter::Options * o ) { LOG_PROFILE(); if ( model == NULL || filename == NULL || filename[0] == '\0' ) { return Model::ERROR_BAD_ARGUMENT; } // Check for identical bone joint names { unsigned c = model->getBoneJointCount(); for ( unsigned i = 0; i < c; i++ ) { for ( unsigned j = i+1; j < c; j++ ) { if ( strcmp( model->getBoneJointName( i ), model->getBoneJointName( j ) ) == 0 ) { model->setFilterSpecificError( "Bone joints must have unique names." ); return Model::ERROR_FILTER_SPECIFIC; } } } } Model::ModelErrorE rval = Model::ERROR_NONE; // Use dynamic cast to determine if the object is of the proper type // If not, create new one that we will be deleted later. // // We need to create one to make sure that the default options we // use in the filter match the default options presented to the // user in the dialog box. release_ptr freeOptions = NULL; m_options = dynamic_cast< Ms3dOptions *>( o ); if ( !m_options ) { freeOptions = static_cast( getDefaultOptions() ); m_options = freeOptions.get(); } string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); m_model = model; Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; // Groups don't share vertices with Milk Shape 3D. Create mesh list // that has unique vertices for each group. UVs/normals are per-face // vertex rather than per-vertex, so vertices do not have to have // unique UVs or normals. MeshList ml; mesh_create_list( ml, model, Mesh::MO_Group | Mesh::MO_Material ); vector & modelVertices = getVertexList( model ); vector & modelTriangles = getTriangleList( model ); vector & modelGroups = getGroupList( model ); vector & modelMaterials = getMaterialList( model ); vector & modelJoints = getJointList( model ); m_dst->writeBytes( (const uint8_t*) MAGIC_NUMBER, strlen(MAGIC_NUMBER) ); int32_t version = 4; m_dst->write( version ); uint16_t t; // write vertices uint16_t numVertices = mesh_list_vertex_count( ml ); m_dst->write( numVertices ); log_debug( "writing %d vertices\n", numVertices ); MeshList::const_iterator it; for ( it = ml.begin(); it != ml.end(); it++ ) { for ( t = 0; t < it->vertices.size(); t++ ) { int modelVert = it->vertices[t].v; Model::Vertex * mvert = modelVertices[modelVert]; MS3DVertex vert; uint8_t refcount = 0; vert.m_flags = 1; for ( int n = 0; n < 3; n++ ) { vert.m_vertex[n] = mvert->m_coord[n]; } vert.m_boneId = model->getPrimaryVertexInfluence( modelVert ); unsigned modelTriangleCount = it->faces.size(); for ( unsigned tri = 0; tri < modelTriangleCount; tri++ ) { for ( unsigned v = 0; v < 3; v++ ) { if ( it->faces[tri].v[v] == t ) { refcount++; } } } vert.m_refCount = refcount; m_dst->write( vert.m_flags ); m_dst->write( vert.m_vertex[0] ); m_dst->write( vert.m_vertex[1] ); m_dst->write( vert.m_vertex[2] ); m_dst->write( vert.m_boneId ); m_dst->write( vert.m_refCount ); } } // write triangles uint16_t numTriangles = (uint16_t) mesh_list_face_count( ml ); m_dst->write( numTriangles ); log_debug( "writing %d triangles\n", numTriangles ); int vertBase = 0; int meshNum = 0; for ( it = ml.begin(); it != ml.end(); it++ ) { for ( t = 0; t < it->faces.size(); t++ ) { int modelTri = it->faces[t].modelTri; Model::Triangle * mtri = modelTriangles[modelTri]; MS3DTriangle tri; tri.m_flags = 1; for ( int v = 0; v < 3; v++ ) { tri.m_vertexIndices[v] = it->faces[t].v[v] + vertBase; tri.m_s[v] = mtri->m_s[v]; tri.m_t[v] = 1.0 - mtri->m_t[v]; for ( int n = 0; n < 3; n++ ) { tri.m_vertexNormals[v][n] = mtri->m_vertexNormals[v][n]; } } tri.m_groupIndex = meshNum; tri.m_smoothingGroup = 0; m_dst->write( tri.m_flags ); m_dst->write( tri.m_vertexIndices[0] ); m_dst->write( tri.m_vertexIndices[1] ); m_dst->write( tri.m_vertexIndices[2] ); m_dst->write( tri.m_vertexNormals[0][0] ); m_dst->write( tri.m_vertexNormals[0][1] ); m_dst->write( tri.m_vertexNormals[0][2] ); m_dst->write( tri.m_vertexNormals[1][0] ); m_dst->write( tri.m_vertexNormals[1][1] ); m_dst->write( tri.m_vertexNormals[1][2] ); m_dst->write( tri.m_vertexNormals[2][0] ); m_dst->write( tri.m_vertexNormals[2][1] ); m_dst->write( tri.m_vertexNormals[2][2] ); m_dst->write( tri.m_s[0] ); m_dst->write( tri.m_s[1] ); m_dst->write( tri.m_s[2] ); m_dst->write( tri.m_t[0] ); m_dst->write( tri.m_t[1] ); m_dst->write( tri.m_t[2] ); m_dst->write( tri.m_smoothingGroup ); m_dst->write( tri.m_groupIndex ); } vertBase += it->vertices.size(); meshNum++; } // write groups uint16_t numGroups = ml.size(); m_dst->write( numGroups ); log_debug( "writing %d groups\n", numGroups ); int triBase = 0; for ( it = ml.begin(); it != ml.end(); it++ ) { Model::Group * grp = NULL; if ( it->group >= 0 ) { grp = modelGroups[it->group]; } uint8_t flags = 0; m_dst->write( flags ); char groupname[32]; if ( grp ) PORT_snprintf( groupname, sizeof(groupname), "%s", grp->m_name.c_str() ); else strcpy( groupname, "Ungrouped" ); m_dst->writeBytes( (const uint8_t*) groupname, sizeof(groupname) ); uint16_t groupTriangles = it->faces.size(); m_dst->write( groupTriangles ); for ( uint16_t n = 0; n < groupTriangles; n++ ) { uint16_t index = n + triBase; m_dst->write( index ); } uint8_t material = static_cast(~0); if ( grp ) material = grp->m_materialIndex; m_dst->write( material ); triBase += it->faces.size(); } uint16_t numMaterials = modelMaterials.size(); m_dst->write( numMaterials ); log_debug( "writing %d materials\n", numMaterials ); for ( t = 0; t < numMaterials; t++ ) { Model::Material * mmat = modelMaterials[t]; MS3DMaterial mat; PORT_snprintf( mat.m_name, sizeof( mat.m_name ), "%s", mmat->m_name.c_str() ); string texturePath; texturePath = getRelativePath( modelPath.c_str(), mmat->m_filename.c_str() ); PORT_snprintf( mat.m_texture, sizeof( mat.m_texture ), "%s", texturePath.c_str() ); texturePath = getRelativePath( modelPath.c_str(), mmat->m_alphaFilename.c_str() ); PORT_snprintf( mat.m_alphamap, sizeof( mat.m_alphamap ), "%s", texturePath.c_str() ); replaceSlash( mat.m_texture ); replaceSlash( mat.m_alphamap ); for ( int n = 0; n < 4; n++ ) { mat.m_ambient[n] = mmat->m_ambient[n]; mat.m_diffuse[n] = mmat->m_diffuse[n]; mat.m_specular[n] = mmat->m_specular[n]; mat.m_emissive[n] = mmat->m_emissive[n]; } mat.m_shininess = mmat->m_shininess; mat.m_transparency = 1.0; mat.m_mode = 0; m_dst->writeBytes( (const uint8_t*) mat.m_name, sizeof(mat.m_name) ); m_dst->write( mat.m_ambient[0] ); m_dst->write( mat.m_ambient[1] ); m_dst->write( mat.m_ambient[2] ); m_dst->write( mat.m_ambient[3] ); m_dst->write( mat.m_diffuse[0] ); m_dst->write( mat.m_diffuse[1] ); m_dst->write( mat.m_diffuse[2] ); m_dst->write( mat.m_diffuse[3] ); m_dst->write( mat.m_specular[0] ); m_dst->write( mat.m_specular[1] ); m_dst->write( mat.m_specular[2] ); m_dst->write( mat.m_specular[3] ); m_dst->write( mat.m_emissive[0] ); m_dst->write( mat.m_emissive[1] ); m_dst->write( mat.m_emissive[2] ); m_dst->write( mat.m_emissive[3] ); m_dst->write( mat.m_shininess ); m_dst->write( mat.m_transparency ); m_dst->write( mat.m_mode ); m_dst->writeBytes( (const uint8_t*) mat.m_texture, sizeof(mat.m_texture) ); m_dst->writeBytes( (const uint8_t*) mat.m_alphamap, sizeof(mat.m_alphamap) ); } float32_t fps = 30.0f; if ( model->getAnimCount( Model::ANIMMODE_SKELETAL ) > 0 ) { fps = model->getAnimFPS( Model::ANIMMODE_SKELETAL, 0 ); } if ( fps <= 0.0 ) { fps = 30.0f; } float32_t currentTime = 1.0; int32_t numFrames = model->getNumFrames(); double spf = 1.0 / fps; m_dst->write( fps ); m_dst->write( currentTime ); m_dst->write( numFrames ); uint16_t numJoints = modelJoints.size(); m_dst->write( numJoints ); for ( t = 0; t < numJoints; t++ ) { Model::Joint * mjoint = modelJoints[t]; MS3DJoint joint; PORT_snprintf( joint.m_name, sizeof(joint.m_name), "%s", mjoint->m_name.c_str() ); if ( mjoint->m_parent >= 0 ) { PORT_snprintf( joint.m_parentName, sizeof(joint.m_parentName), "%s", modelJoints[ mjoint->m_parent ]->m_name.c_str() ); } else { joint.m_parentName[0] = '\0'; } joint.m_flags = 8; for ( int i = 0; i < 3; i++ ) { joint.m_rotation[i] = mjoint->m_localRotation[i]; joint.m_translation[i] = mjoint->m_localTranslation[i]; } unsigned animcount = model->getAnimCount( Model::ANIMMODE_SKELETAL ); unsigned framecount = 0; unsigned prevcount = 0; unsigned a = 0; unsigned f = 0; unsigned rotcount = 0; unsigned transcount = 0; double x = 0; double y = 0; double z = 0; for ( a = 0; a < animcount; a++ ) { framecount = model->getAnimFrameCount( Model::ANIMMODE_SKELETAL, a ); for ( f = 0; f < framecount; f++ ) { if ( model->getSkelAnimKeyframe( a, f, t, true, x, y, z ) ) { rotcount++; } if ( model->getSkelAnimKeyframe( a, f, t, false, x, y, z ) ) { transcount++; } } } joint.m_numRotationKeyframes = rotcount; joint.m_numTranslationKeyframes = transcount; log_debug( "rotation: %d\n", rotcount ); log_debug( "translation: %d\n", transcount ); m_dst->write( joint.m_flags ); m_dst->writeBytes( (const uint8_t*) joint.m_name, sizeof(joint.m_name) ); m_dst->writeBytes( (const uint8_t*) joint.m_parentName, sizeof(joint.m_parentName) ); m_dst->write( joint.m_rotation[0] ); m_dst->write( joint.m_rotation[1] ); m_dst->write( joint.m_rotation[2] ); m_dst->write( joint.m_translation[0] ); m_dst->write( joint.m_translation[1] ); m_dst->write( joint.m_translation[2] ); m_dst->write( joint.m_numRotationKeyframes ); m_dst->write( joint.m_numTranslationKeyframes ); // Rotation keyframes prevcount = 0; for ( a = 0; a < animcount; a++ ) { framecount = model->getAnimFrameCount( Model::ANIMMODE_SKELETAL, a ); for ( f = 0; f < framecount; f++ ) { if ( model->getSkelAnimKeyframe( a, f, t, true, x, y, z ) ) { MS3DKeyframe keyframe; keyframe.m_time = ((double) (prevcount + f + 1)) * spf; log_debug( "keyframe time: %f\n", keyframe.m_time ); keyframe.m_time = keyframe.m_time; keyframe.m_parameter[0] = x; keyframe.m_parameter[1] = y; keyframe.m_parameter[2] = z; m_dst->write( keyframe.m_time ); m_dst->write( keyframe.m_parameter[0] ); m_dst->write( keyframe.m_parameter[1] ); m_dst->write( keyframe.m_parameter[2] ); } } prevcount += framecount; } // Translation keyframes prevcount = 0; for ( a = 0; a < animcount; a++ ) { framecount = model->getAnimFrameCount( Model::ANIMMODE_SKELETAL, a ); for ( f = 0; f < framecount; f++ ) { if ( model->getSkelAnimKeyframe( a, f, t, false, x, y, z ) ) { MS3DKeyframe keyframe; keyframe.m_time = ((double) (prevcount + f + 1)) * spf; log_debug( "keyframe time: %f\n", keyframe.m_time ); keyframe.m_time = keyframe.m_time; keyframe.m_parameter[0] = x; keyframe.m_parameter[1] = y; keyframe.m_parameter[2] = z; m_dst->write( keyframe.m_time ); m_dst->write( keyframe.m_parameter[0] ); m_dst->write( keyframe.m_parameter[1] ); m_dst->write( keyframe.m_parameter[2] ); } } } prevcount += framecount; } int32_t subVersion = m_options->m_subVersion; if ( subVersion == 1 || subVersion == 2 ) { // Remember some values in meta data char value[128]; sprintf( value, "%d", subVersion ); m_model->updateMetaData( "ms3d_sub_version", value ); if ( subVersion == 2 ) { sprintf( value, "%x", m_options->m_vertexExtra ); m_model->updateMetaData( "ms3d_vertex_extra", value ); } writeCommentSection(); writeVertexWeightSection( ml ); // TODO joint color //writeJointColorSection(); } rval = Model::Model::ERROR_NONE; m_options = NULL; return rval; } void Ms3dFilter::writeCommentSection() { // This is always 1 int32_t subVersion = 1; m_dst->write( subVersion ); log_debug( "writing comments subversion %d\n", subVersion ); int32_t numComments = 0; m_dst->write( numComments ); // groups m_dst->write( numComments ); // materials m_dst->write( numComments ); // joints m_dst->write( numComments ); // model } void Ms3dFilter::writeVertexWeightSection( const MeshList & ml ) { int32_t subVersion = m_options->m_subVersion; if ( subVersion < 1 || subVersion > 2 ) { subVersion = 1; } m_dst->write( subVersion ); log_debug( "writing vertex weights subversion %d\n", subVersion ); Model::InfluenceList ilist; int vwritten = 0; MeshList::const_iterator it; for ( it = ml.begin(); it != ml.end(); it++ ) { // FIXME remove debug //fprintf( stderr, "writing influences for mesh\n" ); int vcount = it->vertices.size(); for ( int v = 0; v < vcount; v++ ) { // FIXME remove debug //fprintf( stderr, " mesh vertex %d (%d) is model vertex %d\n", v, vwritten, it->vertices[v].v ); ilist.clear(); if (!m_model->getVertexInfluences( it->vertices[v].v, ilist )) log_error( "get influences failed for vertex %d\n", it->vertices[v].v ); ilist.sort(); writeVertexWeight( subVersion, ilist ); ++vwritten; } } } void Ms3dFilter::writeJointColorSection() { int32_t subVersion = m_options->m_subVersion; m_dst->write( subVersion ); log_debug( "writing joint color subversion %d\n", subVersion ); int bcount = m_model->getBoneJointCount(); for ( int b = 0; b < bcount; b++ ) { for ( int t = 0; t < 3; t++ ) { int ic = 0xff & (m_options->m_jointColor >> (t*8)); float fc = static_cast(ic) / 255.0; m_dst->write( fc ); } } } void Ms3dFilter::writeVertexWeight( int subVersion, const Model::InfluenceList & ilist ) { int8_t boneId[4] = { -1, -1, -1, -1 }; uint8_t weight[4] = { 0, 0, 0, 0 }; int rawWeight[4] = { 0, 0, 0, 0 }; int totalWeight = 0; Model::InfluenceList::const_reverse_iterator it; int index = 0; for ( it = ilist.rbegin(); index < 4 && it != ilist.rend(); it++ ) { totalWeight += static_cast(it->m_weight * 100.0); boneId[ index ] = it->m_boneId; rawWeight[ index ] = static_cast(it->m_weight * 100.0); index++; } int maxWeight = (subVersion == 1) ? 255 : 100; index = 0; for ( it = ilist.rbegin(); index < 4 && it != ilist.rend(); it++ ) { if ( totalWeight > 0 ) weight[ index ] = (uint8_t) (rawWeight[ index ] * (double) maxWeight / (double) totalWeight); else weight[ index ] = maxWeight / ilist.size(); index++; } // Yes, this needs to start at 1 (one), boneId[0] is stored // earlier in the file m_dst->write( boneId[1] ); m_dst->write( boneId[2] ); m_dst->write( boneId[3] ); // Yes, this needs to start at 0 (zero), weight[3] is implicit log_debug( "write weights: %d, %d, %d\n", weight[0], weight[1], weight[2] ); m_dst->write( weight[0] ); m_dst->write( weight[1] ); m_dst->write( weight[2] ); if ( subVersion == 2 ) { uint32_t extra = m_options->m_vertexExtra; m_dst->write( extra ); } } void Ms3dFilter::readString( char * buf, size_t len ) { if ( len > 0 ) { m_src->readBytes( (uint8_t *) buf, len ); buf[ len - 1 ] = '\0'; log_debug( "read string: %s\n", buf ); } } bool Ms3dFilter::readCommentSection() { // TODO: We don't actually do anything with these... meta data maybe? log_debug( "reading comments section\n"); int32_t subVersion = 0; m_src->read( subVersion ); log_debug( " sub version: %d\n", subVersion ); int32_t numComments = 0; for ( int c = CT_GROUP; c < CT_MAX; c++ ) { m_src->read( numComments ); log_debug( " comment type %d: %d comments\n", c, numComments ); for ( int n = 0; n < numComments; n++ ) { int32_t index = 0; int32_t length = 0; m_src->read( index ); m_src->read( length ); log_debug( " index %d, %d bytes\n", index, length ); if ( m_src->eof() ) { return false; } uint8_t * tmp = new uint8_t[length+1]; m_src->readBytes( tmp, length ); tmp[length] = '\0'; std::string comment; comment.assign( reinterpret_cast(tmp), length ); log_debug( " comment = %s\n", comment.c_str() ); delete[] tmp; } } return true; } bool Ms3dFilter::readVertexWeightSection() { log_debug( "reading vertex weight section\n"); int32_t subVersion = 0; m_src->read( subVersion ); subVersion = util_clamp( subVersion, 1, 2 ); char value[128]; sprintf( value, "%d", subVersion ); m_model->updateMetaData( "ms3d_sub_version", value ); log_debug( " sub version: %d\n", subVersion ); bool rval = true; VertexWeightList weightList; VertexWeightList::iterator it; int vcount = m_model->getVertexCount(); for ( int v = 0; rval && v < vcount; v++ ) { //log_debug( " vertex: %d\n", v ); rval = readVertexWeight( subVersion, v, weightList ); if ( rval ) { m_model->removeAllVertexInfluences( v ); for ( it = weightList.begin(); it != weightList.end(); it++ ) { m_model->addVertexInfluence( v, it->boneId, Model::IT_Custom, ((double) it->weight) / 100.0 ); } } } return rval; } bool Ms3dFilter::readVertexWeight( int subVersion, int vertex, VertexWeightList & weightList ) { weightList.clear(); int8_t boneIds[4] = { -1, -1, -1, -1 }; uint8_t weights[4] = { 0, 0, 0, 0 }; size_t size = (subVersion == 2) ? 10 : 6; if ( size > m_src->getRemaining() ) { return false; } boneIds[0] = m_model->getVertexBoneJoint( vertex ); int i = 0; for ( i = 0; i < 3; i++ ) { m_src->read( boneIds[i+1] ); //log_debug( " read boneId %d\n", boneIds[i+1] ); } for ( i = 0; i < 3; i++ ) { m_src->read( weights[i] ); if ( subVersion == 1 ) { weights[i] = (uint8_t) ((int) weights[i] * 100 / 255); } //log_debug( " read weights %d\n", boneIds[i+1] ); } if ( subVersion == 2 ) { int32_t extra = 0; m_src->read( extra ); // don't do anything with this } VertexWeightT vw; int total = 0; for ( i = 0; boneIds[i] >= 0 && i < 4; i++ ) { vw.boneId = boneIds[i]; if ( i < 3 ) { vw.weight = weights[i]; total += weights[i]; } else { int diff = 100 - total; vw.weight = (diff > 0) ? diff : 0; } weightList.push_back( vw ); } return true; } bool Ms3dFilter::isSupported( const char * filename ) { if ( filename ) { unsigned len = strlen( filename ); if ( len >= 5 && strcasecmp( &filename[len-5], ".ms3d" ) == 0 ) { return true; } } return false; } list Ms3dFilter::getReadTypes() { list rval; rval.push_back( "*.ms3d" ); return rval; } list Ms3dFilter::getWriteTypes() { list rval; rval.push_back( "*.ms3d" ); return rval; } mm3d-1.3.7/src/libmm3d/dxffilter.h0000644000175000017500000000672010767317432013600 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __DXFFILTER_H #define __DXFFILTER_H #include "modelfilter.h" #include #include #include #include #include class DxfFilter : public ModelFilter { public: DxfFilter(); virtual ~DxfFilter(); Model::ModelErrorE readFile( Model * model, const char * const filename ); Model::ModelErrorE writeFile( Model * model, const char * const filename, ModelFilter::Options * o = NULL ); bool canRead( const char * filename ); bool canWrite( const char * filename ); bool canExport( const char * filename ); bool isSupported( const char * filename ); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); protected: enum _ReadState_e { RS_MAIN, RS_SECTION, RS_HEADER, RS_TABLES, RS_LAYER, RS_ENTITIES, RS_3DFACE, RS_POLYLINE, RS_VERTEX, RS_UNKNOWN, RS_DONE, RS_MAX }; typedef enum _ReadState_e ReadStateE; bool readLine( const char * line ); bool writeLine( const char * line, ... ); bool readMain( const char * line ); bool readSection( const char * line ); bool readHeader( const char * line ); bool readTables( const char * line ); bool readLayer( const char * line ); bool readEntities( const char * line ); bool read3dface( const char * line ); bool readPolyline( const char * line ); bool readVertex( const char * line ); bool readUnknown( const char * line ); void setReadState( ReadStateE state ); void writeHeader(); void writeGroups(); void writeFaces(); void materialPrep(); int getGroupByName( const char * name ); int getGroupByNameColor( const char * name, int colorIndex ); void setMaterialColor( unsigned int material, int colorIndex ); int getMaterialColor( unsigned int material ); bool materialHasColor( unsigned int material ); Model * m_model; DataSource * m_src; DataDest * m_dst; ReadStateE m_state; int m_lastCode; int m_currentGroup; int m_currentColor; bool m_isPolyfaceMesh; bool m_vertexIsValid; bool m_vertexIsFace; float m_coord[4][3]; int m_vertices[4]; int m_baseVertex; std::string m_modelPath; std::string m_modelBaseName; std::string m_modelFullName; std::map m_materialColor; }; #endif // __DXFFILTER_H mm3d-1.3.7/src/libmm3d/mm3dport.h0000644000175000017500000000414010744511346013343 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __MM3DPORT_H #define __MM3DPORT_H #include #include #include #include #include "config.h" #ifdef WIN32 #include #else #include #endif // WIN32 struct _PORT_timeval { unsigned long tv_sec; // seconds unsigned short tv_msec; // milliseconds }; typedef struct _PORT_timeval PORT_timeval; char * PORT_getenv( const char * name ); int PORT_lstat( const char * filename, struct stat * buf ); char * PORT_realpath( const char * path, char * resolved_path, size_t len ); struct tm * PORT_localtime_r( const time_t * timep, struct tm * result ); void PORT_gettimeofday( PORT_timeval * tv ); char * PORT_asctime_r( const struct tm * tmval, char * buf ); int PORT_symlink( const char * oldpath, const char * newpath ); int PORT_mkdir( const char * pathname, mode_t mode ); int PORT_snprintf( char * dest, size_t len, const char * fmt, ... ); int PORT_vsnprintf( char * dest, size_t len, const char * fmt, va_list args ); char * PORT_strcasestr( const char * haystack, const char * needle ); char * PORT_basename( const char * path ); char * PORT_dirname( const char * path ); #ifdef WIN32 inline bool S_ISLNK( mode_t m ) { return false; } #endif // WIN32 #endif //__MM3DPORT_H mm3d-1.3.7/src/libmm3d/filedatasource.cc0000644000175000017500000000527011001024317014713 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "filedatasource.h" #include FileDataSource::FileDataSource( FILE * fp ) : m_fp( fp ), m_mustClose( false ) { if ( m_fp == NULL ) { setErrno( EBADF ); return; } if ( 0 != fseek( m_fp, 0, SEEK_END ) ) { setErrno( errno ); return; } long size = ftell( m_fp ); if ( size < 0 ) { setErrno( EBADF ); return; } if ( 0 != fseek( m_fp, 0, SEEK_SET ) ) { setErrno( errno ); return; } setFileSize( size ); } FileDataSource::FileDataSource( const char * filename ) : m_mustClose( false ) { m_fp = fopen( filename, "rb" ); if ( m_fp == NULL ) { setErrno( errno ); return; } m_mustClose = true; if ( 0 != fseek( m_fp, 0, SEEK_END ) ) { setErrno( errno ); return; } long size = ftell( m_fp ); if ( size < 0 ) { setErrno( errno ); return; } if ( 0 != fseek( m_fp, 0, SEEK_SET ) ) { setErrno( errno ); return; } setFileSize( size ); } FileDataSource::~FileDataSource() { if ( m_mustClose ) close(); } void FileDataSource::internalClose() { if ( m_fp != NULL ) { fclose( m_fp ); m_fp = NULL; } } bool FileDataSource::internalReadAt( off_t offset, const uint8_t ** buf, size_t * bufLen ) { // TODO should assert on buf and bufLen // If we had an error, just keep returning an error if ( errorOccurred() ) return false; if ( offset > (off_t) getFileSize() ) { setUnexpectedEof( true ); return false; } if ( fseek( m_fp, offset, SEEK_SET ) != 0 ) { setErrno( errno ); return false; } size_t bytes = fread( m_buf, 1, BUF_SIZE, m_fp ); if ( ferror( m_fp ) != 0 ) { setErrno( errno ); return false; } *buf = m_buf; *bufLen = bytes; return true; } mm3d-1.3.7/src/libmm3d/md2filter.h0000644000175000017500000000342310744511346013471 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __MD2FILTER_H #define __MD2FILTER_H #include "modelfilter.h" #include class Md2Filter : public ModelFilter { public: Md2Filter(); virtual ~Md2Filter(); Model::ModelErrorE readFile( Model * model, const char * const filename ); Model::ModelErrorE writeFile( Model * model, const char * const filename, ModelFilter::Options * o = NULL ); bool canRead( const char * filename = NULL ) { return true; }; bool canWrite( const char * filename = NULL ) { return true; }; bool canExport( const char * filename = NULL ) { return true; }; bool isSupported( const char * file ); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); protected: int addNeededAnimFrame( Model * model, const char * name ); std::string m_lastAnimFrame; int m_lastAnimIndex; int m_animFrame; }; #endif // __MD2FILTER_H mm3d-1.3.7/src/libmm3d/md3filter.cc0000644000175000017500000024413311027551551013632 00000000000000/* Md3Filter plugin for Misfit Model 3D * * Copyright (c) 2005-2007 Russell Valentine and Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ /* * Original version by Russell Valentine (russ@coldstonelabs.org) * Plugin based off lwofilter.cc and md2filter.cc by Kevin Worcester. * Spec: http://linux.ucla.edu/~phaethon/q3/formats/md3format.html * * Support for player models and animation.cfg added by Kevin Worcester. */ #include "md3filter.h" #include "model.h" #include "texture.h" #include "texmgr.h" #include "log.h" #include "binutil.h" #include "misc.h" #include "filtermgr.h" #include "mm3dport.h" #include "datadest.h" #include "datasource.h" #include "msg.h" #include "translate.h" #include #include #include #include #include #include #include #ifdef PLUGIN #include "pluginapi.h" #include "version.h" static Md3Filter * s_filter = NULL; #endif // PLUGIN // FIXME this should be centralized template class FunctionCaller { public: FunctionCaller( T * obj, void (T::*method)(void) ) { m_obj = obj; m_method = method; } ~FunctionCaller() { (m_obj->*m_method)(); } private: T * m_obj; void (T::*m_method)(void); }; const int MD3_ANIMATIONS = 25; const int HEADER_SIZE = (11 * 4) + MAX_QPATH; const int FRAME_SIZE = ( 3 * ( 3 * 4 ) + 4 + 16 ); const int TAG_SIZE = ( MAX_QPATH + ( 4 * 3 ) + ( 3 * 4 * 3 ) ); const char s_animNames[ MD3_ANIMATIONS ][16] = { "both_death1", "both_dead1", "both_death2", "both_dead2", "both_death3", "both_dead3", "torso_gesture", "torso_attack", "torso_attack2", "torso_drop", "torso_raise", "torso_stand", "torso_stand2", "legs_walkcr", "legs_walk", "legs_run", "legs_back", "legs_swim", "legs_jump", "legs_land", "legs_jumpb", "legs_landb", "legs_idle", "legs_idlecr", "legs_turn", }; int s_animLoop[ MD3_ANIMATIONS ] = { 0, // both_death1 0, // both_dead1 0, // both_death2 0, // both_dead2 0, // both_death3 0, // both_dead3 0, // torso_gesture 0, // torso_attack 0, // torso_attack2 0, // torso_drop 0, // torso_raise 1, // torso_stand 1, // torso_stand2 1, // legs_walkcr 1, // legs_walk 1, // legs_run 1, // legs_back 1, // legs_swim 0, // legs_jump 0, // legs_land 0, // legs_jumpb 0, // legs_landb 1, // legs_idle 1, // legs_idlecr 1, // legs_turn }; int s_animSyncWarning[ MD3_ANIMATIONS ] = { 0, // both_death1 0, // both_dead1 0, // both_death2 0, // both_dead2 0, // both_death3 0, // both_dead3 0, // torso_gesture 1, // torso_attack 1, // torso_attack2 1, // torso_drop 1, // torso_raise 0, // torso_stand 0, // torso_stand2 0, // legs_walkcr 0, // legs_walk 0, // legs_run 0, // legs_back 0, // legs_swim 0, // legs_jump 0, // legs_land 0, // legs_jumpb 0, // legs_landb 0, // legs_idle 0, // legs_idlecr 0, // legs_turn }; Md3Filter::Md3Filter() { } Md3Filter::~Md3Filter() { } Model::ModelErrorE Md3Filter::readFile( Model * model, const char * const filename ) { if ( model && filename && filename[0] ) { // New logic: // // 1) Load each file into memory // 2) Create model structure with vertices, triangles, groups, and skins // for all meshes in all files // a) Set up points // b) Set meshes // c) Make sure vertices are relative to appropriate tag // 3) Load animations // a) Set up points // b) Set meshes // c) Make sure vertices are relative to appropriate tag // // Notes: // // 1) don't add tags multiple times // 2) get correct anim number from anim frame counts // 3) set default vertex coords for meshes that aren't in an animation Md3FileDataList fileList; bool loadAll = false; m_modelPath = ""; m_modelBaseName = ""; string modelFullName = ""; m_pathList.clear(); normalizePath( filename, modelFullName, m_modelPath, m_modelBaseName ); m_modelPath = m_modelPath + string( "/" ); string lowerFile = m_modelPath + fixFileCase( m_modelPath.c_str(), "lower.md3" ); string upperFile = m_modelPath + fixFileCase( m_modelPath.c_str(), "upper.md3" ); string headFile = m_modelPath + fixFileCase( m_modelPath.c_str(), "head.md3" ); if ( strncasecmp( m_modelBaseName.c_str(), "lower.", 6 ) == 0 || strncasecmp( m_modelBaseName.c_str(), "upper.", 6 ) == 0 || strncasecmp( m_modelBaseName.c_str(), "head.", 5 ) == 0 ) { if ( file_exists( lowerFile.c_str() ) && file_exists( upperFile.c_str() ) && file_exists( headFile.c_str() ) ) { log_debug( "have all files for %s\n", m_modelPath.c_str() ); char answer = msg_info_prompt( transll( QT_TRANSLATE_NOOP( "LowLevel", "This looks like a player model.\nDo you want to load all sections?")).c_str(), "Ync" ); if ( answer == 'Y' ) { loadAll = true; model->addMetaData( "MD3_composite", "1" ); } else if ( answer == 'N' ) { model->addMetaData( "MD3_composite", "0" ); } else { return Model::ERROR_CANCEL; } } } if ( loadAll ) { Md3FileDataT fd; fd.section = MS_Lower; fd.modelBaseName = "lower.md3"; fd.modelFile = lowerFile; fd.tag = ""; fd.tagPoint = -1; fd.src = NULL; fd.offsetMeshes = 0; fd.numMeshes = 0; fd.offsetTags = 0; fd.numTags = 0; fd.numFrames = 0; fileList.push_back( fd ); fd.section = MS_Upper; fd.modelBaseName = "upper.md3"; fd.modelFile = upperFile; fd.tag = "tag_torso"; fileList.push_back( fd ); fd.section = MS_Head; fd.modelBaseName = "head.md3"; fd.modelFile = headFile; fd.tag = "tag_head"; fileList.push_back( fd ); } else { Md3FileDataT fd; fd.section = MS_None; fd.modelBaseName = m_modelBaseName; fd.modelFile = filename; fd.tag = ""; fd.tagPoint = -1; fd.src = NULL; fd.offsetMeshes = 0; fd.numMeshes = 0; fd.offsetTags = 0; fd.numTags = 0; fd.numFrames = 0; fileList.push_back( fd ); } Md3FileDataList::iterator it = fileList.begin(); if ( loadAll ) { readAnimations( false ); } for ( it = fileList.begin(); it != fileList.end(); it++ ) { m_modelBaseName = (*it).modelBaseName; // FIXME just return this below on error (and make sure to // explicitly close it) Model::ModelErrorE err = Model::ERROR_NONE; m_src = openInput( (*it).modelFile.c_str(), err ); if ( err != Model::ERROR_NONE ) { m_src->close(); return err; } log_debug( "loading model file %s\n", (*it).modelFile.c_str() ); model->setFilename( modelFullName.c_str() ); m_model = model; Matrix loadMatrix; loadMatrix.setRotationInDegrees( -90, -90, 0 ); int8_t magic[4]; m_src->readBytes( (uint8_t *) magic, sizeof(magic) ); int32_t version = m_src->readI32(); char pk3Name[MAX_QPATH]; readString( pk3Name, sizeof( pk3Name ) ); replaceBackslash( pk3Name ); int32_t flags = m_src->readI32(); int32_t numFrames = m_src->readI32(); int32_t numTags = m_src->readI32(); int32_t numMeshes = m_src->readI32(); int32_t numSkins = m_src->readI32(); int32_t offsetFrames = m_src->readI32(); int32_t offsetTags = m_src->readI32(); int32_t offsetMeshes = m_src->readI32(); int32_t offsetEnd = m_src->readI32(); log_debug( "Magic: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3] ); log_debug( "Version: %d\n", version ); log_debug( "PK3 Name: %s\n", pk3Name ); log_debug( "Flags: %d\n", flags ); log_debug( "Frames: %d\n", numFrames ); log_debug( "Tags: %d\n", numTags ); log_debug( "Meshes: %d\n", numMeshes ); log_debug( "Skins: %d\n", numSkins ); log_debug( "Offset Frames: %d\n", offsetFrames ); log_debug( "Offset Tags: %d\n", offsetTags ); log_debug( "Offset Meshes: %d\n", offsetMeshes ); log_debug( "Offset End: %d\n", offsetEnd ); log_debug( "File Length: %d\n", m_src->getFileSize() ); if ( magic[0] != 'I' && magic[1] != 'D' && magic[2] != 'P' && magic[3] != '3' ) { log_debug( "Bad Magic: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3] ); return Model::ERROR_BAD_MAGIC; } if ( version != MD3_VERSION ) { return Model::ERROR_UNSUPPORTED_VERSION; } Md3PathT mpath; mpath.section = (*it).section; mpath.material = -1; mpath.path = extractPath(pk3Name); log_debug( "extracted model path: %s\n", mpath.path.c_str() ); m_pathList.push_back( mpath ); m_lastMd3Path = mpath.path; // frames // mm3d doesn't need this, but nice to have if you ever need to debug #if 0 m_src->seek( offsetFrames ); for ( int i = 0; i < numFrames; i++ ) { float minBound[3]; for ( int t = 0; t < 3; t++ ) { minBound[t] = m_src->readF32(); } float maxBound[3]; for ( int t = 0; t < 3; t++ ) { maxBound[t] = m_src->readF32(); } float localOrigin[3]; for ( int t = 0; t < 3; t++ ) { localOrigin[t] = m_src->readF32(); } //float radius = m_src->readF32(); char frameName[16]; readString( frameName, sizeof(frameName) ); //log_debug( "Frame %d minBound: %f, %f, %f\n", i, minBound[0], minBound[1], minBound[2] ); //log_debug( "Frame %d maxBound: %f, %f, %f\n", i, maxBound[0], maxBound[1], maxBound[2] ); //log_debug( "Frame %d localOrigin: %f, %f, %f\n", i, localOrigin[0], localOrigin[1], localOrigin[2] ); //log_debug( "Frame %d radius: %f\n", i, radius ); log_debug( "Frame %d name: %s\n", i, frameName ); } #endif // 1 if ( (*it).tag.size() > 0 ) { (*it).tagPoint = m_model->getPointByName( (*it).tag.c_str() ); log_debug( "tag point for %s is %d\n", (*it).tag.c_str(), (*it).tagPoint ); } m_meshVecInfos = new MeshVectorInfoT*[numMeshes]; setPoints( (*it).section, offsetTags, numTags, numFrames, (*it).tagPoint, -1 ); setMeshes( (*it).section, offsetMeshes, numMeshes, (*it).tagPoint, -1 ); (*it).meshVecInfos = m_meshVecInfos; (*it).src = m_src; (*it).offsetMeshes = offsetMeshes; (*it).numMeshes = numMeshes; (*it).offsetTags = offsetTags; (*it).numTags = numTags; (*it).numFrames = numFrames; } if ( fileList.front().numFrames > 1 ) { log_debug( "Model has animation, setting up animation mode.\n" ); if ( m_model->getAnimCount( Model::ANIMMODE_FRAME ) == 0 ) { if ( !loadAll || !readAnimations( true ) ) { int animIndex = m_model->addAnimation( Model::ANIMMODE_FRAME, "AnimFrames" ); m_model->setAnimFPS( Model::ANIMMODE_FRAME, animIndex, 15.0); m_model->setAnimFrameCount( Model::ANIMMODE_FRAME, 0, fileList.front().numFrames ); } } } for ( it = fileList.begin(); it != fileList.end(); it++ ) { m_meshVecInfos = (*it).meshVecInfos; m_src = (*it).src; //Animations int32_t animIndex = 0; if ( (*it).numFrames > 0 ) { setPoints( (*it).section, (*it).offsetTags, (*it).numTags, (*it).numFrames, (*it).tagPoint, animIndex ); setMeshes( (*it).section, (*it).offsetMeshes, (*it).numMeshes, (*it).tagPoint, animIndex ); } } // Set MD3_PATH size_t len = m_pathList.size(); std::string mainStr = ""; size_t i = 0; for ( i = 0; mainStr.empty() && i < len; i++ ) { if ( m_pathList[i].material < 0 ) { mainStr = m_pathList[i].path; break; } } model->addMetaData( "MD3_PATH", mainStr.c_str() ); for ( i = 0; i < len; i++ ) { if ( !m_pathList[i].path.empty() && strcasecmp( m_pathList[i].path.c_str(), mainStr.c_str() ) != 0 ) { std::string key = "MD3_PATH_"; if ( m_pathList[i].material >= 0 ) { const char * name = model->getTextureName( m_pathList[i].material ); key += name ? name : ""; } else { switch ( m_pathList[i].section ) { case MS_Head: key += "head"; break; case MS_Upper: key += "upper"; break; case MS_Lower: key += "lower"; break; default: key += "main"; break; } } model->addMetaData( key.c_str(), m_pathList[i].path.c_str() ); } } // Clean-up for ( it = fileList.begin(); it != fileList.end(); it++ ) { for ( int i = 0; i < (*it).numMeshes; i++ ) { delete[] (*it).meshVecInfos[i]; } delete[] (*it).meshVecInfos; (*it).src->close(); (*it).src = NULL; } return Model::ERROR_NONE; } else { log_error( "no filename supplied for model filter" ); return Model::ERROR_NO_FILE; } } unsigned Md3Filter::readString( char * dest, size_t len ) { m_src->readBytes( (uint8_t *) dest, len ); dest[ len - 1 ]= '\0'; return len; } bool Md3Filter::readAnimations( bool create ) { string animFile = m_modelPath + "animation.cfg"; FILE * fp = fopen( animFile.c_str(), "r" ); int animCount = 0; int animFrames = 0; int animOffset = 0; //m_animMap.clear(); m_animStartFrame.clear(); m_torsoStart = 0; m_legsStart = 0; m_standFrame = 0; m_idleFrame = 0; if ( fp != NULL ) { log_debug( "reading animation.cfg\n" ); char line[256]; while ( fgets(line, sizeof(line), fp ) != NULL ) { if ( strncmp( line, "//", 2 ) == 0 ) { // Comment } else if ( isspace( line[0] ) ) { // Blank } else { int first = 0; int fcount = 0; int loop = 0; int fps = 0; if ( sscanf( line, "%d %d %d %d", &first, &fcount, &loop, &fps ) == 4 ) { log_debug( "got anim frame details\n" ); if ( animCount == 6 ) { m_torsoStart = first; } else if ( animCount == 11 ) { m_standFrame = first; } else if ( animCount == 13 ) { // Some animation files have the leg frames continuously numbered // after the torso frames, others number the legs following the // "both" frames. Here we are adjusting the second case to make // it match the first case by using "animOffset" if ( first == m_torsoStart ) { animOffset = animFrames - m_torsoStart; } m_legsStart = first + animOffset; } else if ( animCount == 22 ) { m_idleFrame = first - (m_legsStart - m_torsoStart) + animOffset; } first += animOffset; if ( first + fcount > animFrames ) { if ( create ) { //m_animMap.push_back( m_model->getAnimCount( Model::ANIMMODE_FRAME ) ); m_animStartFrame.push_back( first ); char * name = NULL; if ( animCount < MD3_ANIMATIONS ) { // I won't change it, I promise name = (char *) s_animNames[ animCount ]; } else { name = strrchr( line, '/' ); if ( name ) { name++; while ( isspace(name[0]) ) { name++; } int end = 0; while ( name[end] && !isspace(name[end]) ) { end++; } name[end] = '\0'; for ( end = 0; line[end]; end++ ) { name[end] = tolower( line[end] ); } } else { name = "Unknown"; } } log_debug( "adding animation '%s'\n", name ); int animIndex = m_model->addAnimation( Model::ANIMMODE_FRAME, s_animNames[ animCount ] ); m_model->setAnimFPS( Model::ANIMMODE_FRAME, animIndex, (double) fps ); m_model->setAnimFrameCount( Model::ANIMMODE_FRAME, animIndex, fcount ); } animFrames += fcount; } else { log_debug( "did not add animation for '%s'\n", s_animNames[ animCount ] ); } animCount++; } else { if ( create ) { char * value = NULL; if ( strncasecmp( line, "sex", 3 ) == 0 ) { // sex (m,f,n) value = &line[3]; while( isspace(value[0]) ) { value++; } int end = 0; while ( value[end] && !isspace( value[end] ) ) { end++; } value[end] = '\0'; m_model->addMetaData( "MD3_sex", value ); } else if ( strncasecmp( line, "footsteps", 9 ) == 0 ) { // footsteps (normal,boot,flesh,mech) value = &line[9]; while( isspace(value[0]) ) { value++; } int end = 0; while ( value[end] && !isspace( value[end] ) ) { end++; } value[end] = '\0'; m_model->addMetaData( "MD3_footsteps", value ); } else if ( strncasecmp( line, "headoffset", 10 ) == 0 ) { // headoffset %d %d %d value = &line[10]; while( isspace(value[0]) ) { value++; } int end = 0; while ( value[end] && value[end] != '\r' && value[end] != '\n' ) { end++; } value[end] = '\0'; m_model->addMetaData( "MD3_headoffset", value ); } else if ( strncasecmp( line, "fixedtorso", 10 ) == 0 ) { m_model->addMetaData( "MD3_fixedtorso", "" ); } else if ( strncasecmp( line, "fixedlegs", 9 ) == 0 ) { m_model->addMetaData( "MD3_fixedlegs", "" ); } else { log_warning( "Unknown meta data: %s", line ); } } } } } fclose( fp ); return true; } return false; } void Md3Filter::setMeshes( MeshSectionE section, int32_t offsetMeshes, int32_t numMeshes, int32_t parentTag, int32_t animIndex ) { Matrix loadMatrix; loadMatrix.setRotationInDegrees( -90, -90, 0 ); double pos[3] = { 0,0,0 }; double rot[3] = { 0,0,0 }; if ( parentTag >= 0 ) { m_model->getPointCoords( parentTag, pos ); m_model->getPointOrientation( parentTag, rot ); loadMatrix.loadIdentity(); loadMatrix.setRotation( rot ); loadMatrix.setTranslation( pos[0], pos[1], pos[2] ); } // Meshes m_src->seek( offsetMeshes ); int32_t meshPos = offsetMeshes; for ( int mesh = 0; mesh < numMeshes; mesh++ ) { //Mesh header int8_t meshMagic[4]; m_src->readBytes( (uint8_t*) meshMagic, sizeof(meshMagic) ); char meshName[MAX_QPATH]; readString( meshName, sizeof( meshName ) ); int32_t meshFlags = m_src->readI32(); int32_t meshFrameCount = m_src->readI32(); int32_t meshShaderCount = m_src->readI32(); int32_t meshVertexCount = m_src->readI32(); int32_t meshTriangleCount = m_src->readI32(); int32_t meshTriangleOffset = m_src->readI32(); int32_t meshShaderOffset = m_src->readI32(); int32_t meshSTOffset = m_src->readI32(); int32_t meshXYZOffset = m_src->readI32(); int32_t meshEndOffset = m_src->readI32(); log_debug( "Mesh %d magic: %c%c%c%c\n", mesh, meshMagic[0], meshMagic[1], meshMagic[2], meshMagic[3] ); log_debug( "Mesh %d name: %s\n", mesh, meshName ); log_debug( "Mesh %d flags: %d\n", mesh, meshFlags ); log_debug( "Mesh %d num_frames: %d\n", mesh, meshFrameCount ); log_debug( "Mesh %d num_shaders: %d\n", mesh, meshShaderCount ); log_debug( "Mesh %d num_vertex: %d\n", mesh, meshVertexCount ); log_debug( "Mesh %d num_triangles: %d\n", mesh, meshTriangleCount ); log_debug( "Mesh %d triangle offset: %d\n", mesh, meshTriangleOffset ); log_debug( "Mesh %d shader offset: %d\n", mesh, meshShaderOffset ); log_debug( "Mesh %d st offset: %d\n", mesh, meshSTOffset ); log_debug( "Mesh %d xyz offset: %d\n", mesh, meshXYZOffset ); log_debug( "Mesh %d end offset: %d\n", mesh, meshEndOffset ); int frameSize = meshVertexCount * 4 * 2; //Load first frame // Vertex m_src->seek( meshPos + meshXYZOffset ); float meshVec[4] = { 0, 0, 0, 1 }; if ( animIndex < 0 ) { int fileFrame = animToFrame( section, -1, 0 ); log_debug( "Using frame %d as default for section %d\n", fileFrame, section ); if ( fileFrame >= meshFrameCount ) { log_error( "mesh %s appears to be missing frame %d for anim %d, using frame %d instead\n", meshName, fileFrame, animIndex, 0 ); fileFrame = 0; } m_src->seek( meshPos + meshXYZOffset + fileFrame * frameSize ); m_meshVecInfos[mesh] = new MeshVectorInfoT[meshVertexCount]; for ( int vert = 0; vert < meshVertexCount; vert++ ) { for ( int n = 0; n < 3; n ++ ) { meshVec[n] = m_src->readI16() * MD3_XYZ_SCALE; } meshVec[3] = 1; m_meshVecInfos[mesh][vert].lng = m_src->readI8(); m_meshVecInfos[mesh][vert].lat = m_src->readI8(); //log_debug("normals lat, lng: %d, %d\n", m_meshVecInfos[mesh][vert].lat, m_meshVecInfos[mesh][vert].lng); loadMatrix.apply( meshVec ); m_meshVecInfos[mesh][vert].id = m_model->addVertex( meshVec[0], meshVec[1], meshVec[2] ); } } else { int acount = m_model->getAnimCount( Model::ANIMMODE_FRAME ); for ( animIndex = 0; animIndex < acount; animIndex++ ) { bool inAnim = animInSection( getSafeName( animIndex), section ); int fcount = m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, animIndex ); for ( int frame = 0; frame < fcount; frame++ ) { int fileFrame = animToFrame( section, animIndex, frame ); if ( fileFrame >= meshFrameCount ) { log_error( "mesh %s appears to be missing frame %d for anim %d, using frame %d instead\n", meshName, fileFrame, animIndex, meshFrameCount - 1 ); fileFrame = meshFrameCount - 1; } m_src->seek( meshPos + meshXYZOffset + fileFrame * frameSize ); if ( parentTag >= 0 ) { m_model->getFrameAnimPointCoords( animIndex, frame, parentTag, pos[0], pos[1], pos[2] ); m_model->getFrameAnimPointRotation( animIndex, frame, parentTag, rot[0], rot[1], rot[2] ); loadMatrix.loadIdentity(); loadMatrix.setRotation( rot ); loadMatrix.setTranslation( pos[0], pos[1], pos[2] ); } Matrix invMatrix; invMatrix.loadIdentity(); if ( parentTag >= 0 ) { m_model->getPointCoords( parentTag, pos ); m_model->getPointOrientation( parentTag, rot ); invMatrix.setRotation( rot ); invMatrix.setTranslation( pos[0], pos[1], pos[2] ); } else { invMatrix.setRotationInDegrees( -90, -90, 0 ); } invMatrix = invMatrix.getInverse(); for ( int vert = 0; vert < meshVertexCount; vert++ ) { if ( inAnim ) { for ( int n = 0; n < 3; n ++ ) { meshVec[n] = m_src->readI16() * MD3_XYZ_SCALE; } m_meshVecInfos[mesh][vert].lng = m_src->readI8(); m_meshVecInfos[mesh][vert].lat = m_src->readI8(); //log_debug("normals lat, lng: %d, %d\n", m_meshVecInfos[mesh][vert].lat, m_meshVecInfos[mesh][vert].lng); } else { double coord[3]; m_model->getVertexCoords( m_meshVecInfos[mesh][vert].id, coord ); meshVec[0] = coord[0]; meshVec[1] = coord[1]; meshVec[2] = coord[2]; meshVec[3] = 1; invMatrix.apply( meshVec ); } meshVec[3] = 1; loadMatrix.apply( meshVec ); m_model->setQuickFrameAnimVertexCoords( animIndex, frame, m_meshVecInfos[mesh][vert].id, meshVec[0], meshVec[1], meshVec[2] ); } } } } if ( animIndex < 0 ) { // Triangle m_src->seek( meshPos + meshTriangleOffset ); int32_t triang[meshTriangleCount][3]; unsigned tri[meshTriangleCount]; int32_t groupId = m_model->addGroup( meshName ); for ( int t = 0; t < meshTriangleCount; t++ ) { for ( int n = 0; n < 3; n++ ) { triang[t][n] = m_src->readI32(); } tri[t]= m_model->addTriangle( m_meshVecInfos[mesh][triang[t][2]].id, m_meshVecInfos[mesh][triang[t][1]].id, m_meshVecInfos[mesh][triang[t][0]].id ); m_model->addTriangleToGroup( groupId, tri[t] ); } //Vertex Texture Coords m_src->seek( meshPos + meshSTOffset ); for (int v = 0; v < meshVertexCount; v++ ) { m_meshVecInfos[mesh][v].s = m_src->readF32(); m_meshVecInfos[mesh][v].t = m_src->readF32(); } //Textures/Shaders vector & modelMaterials = getMaterialList( m_model ); m_src->seek( meshPos + meshShaderOffset ); char shaderName[MAX_QPATH]; readString(shaderName, sizeof( shaderName )); int32_t shaderIndex = m_src->readI32(); replaceBackslash( shaderName ); string shaderFileName = string( shaderName ); shaderFileName = getFileNameFromPath( shaderName ); string skin = m_modelPath+shaderFileName; string shaderFullName; string shaderFullPath; string shaderBaseName; normalizePath( skin.c_str(), shaderFullName, shaderFullPath, shaderBaseName ); log_debug( "Shader Name: %s\n", shaderName ); log_debug( "Shader Index: %d\n", shaderIndex ); log_debug( "Shader FileName: %s\n", shaderFileName.c_str() ); log_debug( "Shader full name: %s\n", shaderFullName.c_str() ); log_debug( "Shader full path: %s\n", shaderFullPath.c_str() ); log_debug( "Shader base name: %s\n", shaderBaseName.c_str() ); string textureFile = m_modelPath+shaderBaseName; textureFile = fixAbsolutePath( m_modelPath.c_str(), textureFile.c_str() ); textureFile = getAbsolutePath( m_modelPath.c_str(), textureFile.c_str() ); log_debug( "textureFile = %s\n", textureFile.c_str() ); bool textureFound = false; int matId = -1; //First check for skins matId = setSkins( meshName ); if (matId >= 0) { textureFound = true; } if ( ! textureFound ) { textureFile = findTexture( shaderBaseName, shaderName ); if ( textureFile.size() > 0) { //If we already loaded this texture before int checkId = materialsCheck( textureFile ); if (checkId >= 0) { matId = checkId; textureFound = true; } else { textureFound = true; Model::Material * mat = Model::Material::get(); mat->m_name = shaderBaseName; for ( int m = 0; m < 3; m++ ) { mat->m_ambient[m] = 0.2; mat->m_diffuse[m] = 0.8; mat->m_specular[m] = 0.0; mat->m_emissive[m] = 0.0; } mat->m_ambient[3] = 1.0; mat->m_diffuse[3] = 1.0; mat->m_specular[3] = 1.0; mat->m_emissive[3] = 1.0; mat->m_shininess = 0.0; mat->m_alphaFilename = ""; mat->m_name = getFileNameFromPath( textureFile.c_str() ); mat->m_filename = textureFile; modelMaterials.push_back( mat ); matId = modelMaterials.size()-1; } } } if (textureFound) { log_debug( "skin : '%s'\n", textureFile.c_str() ); m_model->setGroupTextureId( groupId, matId ); Md3PathT mpath; mpath.section = section; mpath.material = matId; mpath.path = extractPath(shaderName); m_pathList.push_back( mpath ); m_lastMd3Path = mpath.path; log_debug( "extracted shader path: %s\n", mpath.path.c_str() ); } //Texture Mapping // // Add texture coordinates even if we didn't find the texture // (user may load it manually) for ( int t = 0; t < meshTriangleCount; t++ ) { m_model->setTextureCoords( tri[t], 0, m_meshVecInfos[mesh][triang[t][2]].s, 1.0-m_meshVecInfos[mesh][triang[t][2]].t ); m_model->setTextureCoords( tri[t], 1, m_meshVecInfos[mesh][triang[t][1]].s, 1.0-m_meshVecInfos[mesh][triang[t][1]].t ); m_model->setTextureCoords( tri[t], 2, m_meshVecInfos[mesh][triang[t][0]].s, 1.0-m_meshVecInfos[mesh][triang[t][0]].t ); } } //Goto end meshPos = meshPos + meshEndOffset; log_debug( "mesh position is %d\n", meshPos ); m_src->seek( meshPos ); } return; } //Give it file basename and it will find a texture like it. //Returns full path std::string Md3Filter::findTexture( std::string baseName, std::string shaderFullName ) { //Lets go through everything see if we could find a texture if ( baseName.size() <= 0 || strcmp( baseName.c_str(), "." ) == 0 ) { return ""; } TextureManager * texmgr = TextureManager::getInstance(); //log_debug( "looking for texture files with name like: %s\n", baseName.c_str() ); char * noext = strdup( baseName.c_str() ); char * ext = strrchr( noext, '.' ); if ( ext ) { ext[0] = '\0'; } list files; getFileList( files, m_modelPath.c_str(), noext ); list::iterator it; free( noext ); // try current directory for ( it = files.begin(); it != files.end(); it++ ) { string texturePath = m_modelPath + (*it); texturePath = getAbsolutePath( m_modelPath.c_str(), texturePath.c_str() ); //log_debug( "checking %s\n", texturePath.c_str() ); if ( texmgr->getTexture( texturePath.c_str() ) ) { //log_debug( " %s is a skin\n", texturePath.c_str() ); return texturePath; } } // try shader path if ( !m_lastMd3Path.empty() ) { size_t len = m_lastMd3Path.size(); if ( m_modelPath.size() > len ) { std::string path = m_modelPath; path.resize( path.size() - len ); path += shaderFullName; return path; } } return shaderFullName; } //If a material with filename already exists reutrn id, otherwise -1 int32_t Md3Filter::materialsCheck( std::string textureFullName ) { vector & modelMaterials = getMaterialList( m_model ); for ( unsigned i = 0; i < modelMaterials.size(); i++ ) { if ( strcmp( modelMaterials[i]->m_filename.c_str(), textureFullName.c_str() ) == 0 ) { return i; } } return -1; } //Will load all the textures in a skin file for a meshName //it will return the default material. int32_t Md3Filter::setSkins( char *meshName ) { if ( strlen(meshName) < 0 ) { log_debug( "setSkins() no meshName.\n" ); return -1; } int matId = -1; vector & modelMaterials = getMaterialList( m_model ); //Find all the skin files list files; list::iterator it; char * noext = strdup( m_modelBaseName.c_str() ); char * ext = strrchr( noext, '.' ); if ( ext ) { ext[0] = '\0'; } char *base = (char *) malloc( sizeof( char ) * ( strlen(noext)+2 ) ); strcpy( base, noext ); strcat( base, "_" ); getFileList( files, m_modelPath.c_str(), base ); bool defaultSet = false; for ( it = files.begin(); it != files.end(); it++ ) { bool isDefault = false; string fileName = (*it); string fullName = m_modelPath + fileName; fullName = getAbsolutePath( m_modelPath.c_str(), fullName.c_str() ); //Only take the ones with .skin extension noext = strdup( fileName.c_str() ); ext = strrchr( noext, '.' ); if ( PORT_strcasestr( fileName.c_str(), "_default.skin" ) != NULL ) { log_debug( "is default\n" ); isDefault = true; } if ( strcmp( ext, ".skin" ) == 0 ) { FILE * fp = fopen( fullName.c_str(), "rb" ); if ( fp == NULL ) { log_error( "%s: file does not exist\n", fileName.c_str() ); continue; } if ( errno == EPERM ) { log_error( "%s: access denied\n", fileName.c_str() ); continue; } fseek( fp, 0, SEEK_END ); unsigned fileLength = ftell( fp ); fseek( fp, 0, SEEK_SET ); if ( fileLength <= 0 ) { log_error( "%s: empty file\n", fileName.c_str() ); fclose( fp ); continue; } char *skinBuf = (char *)malloc( fileLength ); if ( fread( skinBuf, fileLength, 1, fp ) != 1 ) { delete[] skinBuf; log_error( "%s: could not read file\n", fileName.c_str() ); fclose( fp ); free( skinBuf ); continue; } fclose( fp ); //XXX: There has got to be a better way to do this, maybe ifstream? char *sep = (char *) malloc( sizeof( char ) * ( strlen( meshName ) + 2 ) ); strcpy( sep, meshName ); strcat( sep, "," ); char * line = (char *) PORT_strcasestr( skinBuf, (char *) meshName); char * file; if ( line ) { char *nl = strchr( line, '\n' ); if ( nl ) { nl[0] = '\0'; nl = strchr( line, '\r' ); if ( nl ) { nl[0] = '\0'; } } file = strchr( line, ',' ); if ( file && strlen( file ) > 1 ) { file++; log_debug( "texture file is: %s\n", file ); } else { continue; } } else { continue; } //Whew! we have the file now lets load it up. replaceBackslash( file ); string textureBaseName = getFileNameFromPath( file ); string textureFullName = findTexture( textureBaseName, file ); if ( textureFullName.size() > 0 ) { int checkId = materialsCheck(textureFullName); //If already loaded if ( checkId >= 0 ) { if ( ! defaultSet ) { matId = checkId; if ( isDefault ) { defaultSet = true; } } } else { Model::Material * mat = Model::Material::get(); mat->m_name = textureBaseName; for ( int m = 0; m < 3; m++ ) { mat->m_ambient[m] = 0.2; mat->m_diffuse[m] = 0.8; mat->m_specular[m] = 0.0; mat->m_emissive[m] = 0.0; } mat->m_ambient[3] = 1.0; mat->m_diffuse[3] = 1.0; mat->m_specular[3] = 1.0; mat->m_emissive[3] = 1.0; mat->m_shininess = 0.0; mat->m_filename = textureFullName; mat->m_alphaFilename = ""; mat->m_name = getFileNameFromPath( textureFullName.c_str() ); modelMaterials.push_back( mat ); if ( ! defaultSet ) { matId = modelMaterials.size()-1; if ( isDefault ) { defaultSet = true; } } } } free( skinBuf ); } } free( base ); return matId; } //If animIndex < 0 it will setup the initial points //otherwise it will set the position. void Md3Filter::setPoints( MeshSectionE section, int32_t offsetTags, int32_t numTags, int32_t numFrames, int32_t parentTag, int32_t animIndex ) { Matrix loadMatrix; loadMatrix.setRotationInDegrees( -90, -90, 0 ); double pos[3] = { 0,0,0 }; double rot[3] = { 0,0,0 }; if ( parentTag >= 0 ) { m_model->getPointCoords( parentTag, pos ); m_model->getPointOrientation( parentTag, rot ); loadMatrix.loadIdentity(); loadMatrix.setRotation( rot ); loadMatrix.setTranslation( pos[0], pos[1], pos[2] ); } const int TAG_SIZE = (64 + 3*4 + 9*4); int frameSize = numTags * TAG_SIZE; // Tags int animCount = m_model->getAnimCount( Model::ANIMMODE_FRAME ); if ( animIndex < 0 ) { animCount = 0; } for ( animIndex = animIndex; animIndex < animCount; animIndex++ ) { int frameCount = m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, animIndex ); if ( animIndex < 0 ) { frameCount = 1; } for ( int f = 0; f < frameCount; f++ ) { int fileFrame = animToFrame( section, animIndex, f ); if ( animIndex < 0 ) { log_debug( "Using frame %d as default for tag section %d\n", fileFrame, section ); } if ( fileFrame >= numFrames ) { log_error( "tag section appears to be missing frame %d for anim %d, using frame %d instead\n", fileFrame, animIndex, numFrames - 1 ); fileFrame = numFrames - 1; } /* log_debug( "section %d anim %d frame %d is file frame %d\n", section, animIndex, f, fileFrame ); */ m_src->seek( offsetTags + (fileFrame * frameSize) ); if ( animIndex >= 0 && parentTag >= 0 ) { m_model->getFrameAnimPointCoords( animIndex, f, parentTag, pos[0], pos[1], pos[2] ); m_model->getFrameAnimPointRotation( animIndex, f, parentTag, rot[0], rot[1], rot[2] ); loadMatrix.loadIdentity(); loadMatrix.setRotation( rot ); loadMatrix.setTranslation( pos[0], pos[1], pos[2] ); } for ( int i = 0; i < numTags; i++ ) { char tagName[MAX_QPATH]; readString( tagName, sizeof( tagName ) ); double posVector[3]; for ( int t = 0; t < 3; t++ ) { posVector[t] = m_src->readF32(); } Matrix curMatrix; double rotVector[3]; curMatrix.setTranslation( posVector ); for ( int t = 0; t < 3; t++ ) { for ( int s = 0; s < 3; s++ ) { curMatrix.set( t, s, m_src->readF32() ); } } curMatrix = curMatrix * loadMatrix; curMatrix.getRotation( rotVector ); curMatrix.getTranslation( posVector ); if ( animIndex < 0 ) { // Only add the point if we don't already have one of the same name int p = m_model->getPointByName( tagName ); if ( p < 0 ) { m_model->addPoint( tagName, posVector[0], posVector[1], posVector[2], rotVector[0], rotVector[1], rotVector[2] ); } } else { int p = m_model->getPointByName( tagName ); if ( p != parentTag ) { m_model->setFrameAnimPointCoords( animIndex, f, p, posVector[0], posVector[1], posVector[2] ); m_model->setFrameAnimPointRotation( animIndex, f, p, rotVector[0], rotVector[1], rotVector[2] ); } } } } } return; } int Md3Filter::animToFrame( MeshSectionE section, int anim, int frame ) { if ( anim < 0 ) { // Not an animation, use first frame switch ( section ) { case MS_Lower: return m_idleFrame; break; case MS_Upper: return m_standFrame; break; default: break; } return 0; } if ( !animInSection( getSafeName( anim ), section ) ) { // Not valid for this section, use first frame switch ( section ) { case MS_Lower: return m_idleFrame; break; case MS_Upper: return m_standFrame; break; default: break; } return 0; } if ( anim >= (int) m_animStartFrame.size() ) { // Not a valid animation return frame; } int fileFrame = m_animStartFrame[anim] + frame; switch ( section ) { case MS_None: // Not a multi-MD3 model, use specified frame return frame; case MS_Lower: if ( fileFrame > m_torsoStart ) { fileFrame -= (m_legsStart - m_torsoStart); } return fileFrame; case MS_Upper: return fileFrame; case MS_Head: default: // No head animations, use first frame return 0; } return frame; } bool Md3Filter::animInSection( std::string animName, MeshSectionE section ) { if ( section == MS_Head ) { return false; } if ( section == MS_None ) { // Uh... sure... return true; } if ( strncasecmp( animName.c_str(), "torso_", 6 ) == 0 ) { if ( section == MS_Upper ) return true; else return false; } if ( strncasecmp( animName.c_str(), "legs_", 5 ) == 0 ) { if ( section == MS_Lower ) return true; else return false; } // It's a "both_" animation, or something weird if ( strncasecmp( animName.c_str(), "both_", 5 ) == 0 ) return true; else return false; } bool Md3Filter::groupInSection( std::string groupName, MeshSectionE section ) { if ( section == MS_None ) { // not a player model, anything goes return true; } if ( groupName[1] == '_' ) { switch ( toupper( groupName[0] ) ) { case 'U': if ( section == MS_Upper ) { return true; } break; case 'L': if ( section == MS_Lower ) { return true; } break; case 'H': if ( section == MS_Head ) { return true; } break; default: break; } } return false; } bool Md3Filter::tagInSection( std::string tagName, MeshSectionE section ) { if ( section == MS_None ) { // not a player model, anything goes return true; } if ( strcasecmp( tagName.c_str(), "tag_torso" ) == 0 ) { if ( section != MS_Head ) { return true; } } else if ( strcasecmp( tagName.c_str(), "tag_head" ) == 0 ) { if ( section != MS_Lower ) { return true; } } else if ( strcasecmp( tagName.c_str(), "tag_weapon" ) == 0 ) { if ( section == MS_Upper ) { return true; } } return false; } bool Md3Filter::tagIsSectionRoot( std::string tagName, MeshSectionE section ) { switch ( section ) { case MS_Upper: if ( strcasecmp( tagName.c_str(), "tag_torso" ) == 0 ) { return true; } break; case MS_Head: if ( strcasecmp( tagName.c_str(), "tag_head" ) == 0 ) { return true; } break; case MS_Lower: case MS_None: // No root tag break; default: break; } return false; } std::string Md3Filter::getSafeName( unsigned int anim ) { std::string animName = "none"; if ( anim < m_model->getAnimCount( Model::ANIMMODE_FRAME ) ) { animName = m_model->getAnimName( Model::ANIMMODE_FRAME, anim ); } return animName; } Model::ModelErrorE Md3Filter::writeFile( Model * model, const char * const filename, ModelFilter::Options * ) { if ( model && filename && filename[0] ) { unsigned tcount = model->getTriangleCount(); for ( unsigned t = 0; t < tcount; ++t ) { if ( model->getTriangleGroup( t ) < 0 ) { model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "MD3 export requires all faces to be grouped." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } } m_model = model; MeshList meshes; // MD3 does not allow a single vertex to have more than one texture // coordinate or normal. MM3D does. The mesh_create_list function will // break the model up into meshes where vertices meet the MD3 criteria. // See mesh.h for details. mesh_create_list( meshes, model ); string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; normalizePath( filename, modelFullName, modelPath, modelBaseName ); m_modelPath = modelPath; bool saveAsPlayer = true; bool haveUpper = false; bool haveLower = false; unsigned gcount = m_model->getGroupCount(); for ( unsigned g = 0; g < gcount; g++ ) { std::string name = m_model->getGroupName( g ); if ( name[1] == '_' ) { switch ( toupper( name[0] ) ) { case 'U': haveUpper = true; break; case 'L': haveLower = true; break; default: break; } } } if ( haveUpper && haveLower ) { if ( m_model->getPointByName( "tag_torso" ) < 0 || m_model->getPointByName( "tag_weapon" ) < 0 || m_model->getPointByName( "tag_head" ) < 0 ) { // missing required tags for player model saveAsPlayer = false; } } else { // don't have the proper groups to save as a player model saveAsPlayer = false; } if ( saveAsPlayer ) { if ( strncasecmp( modelBaseName.c_str(), "lower.", 6 ) == 0 || strncasecmp( modelBaseName.c_str(), "upper.", 6 ) == 0 || strncasecmp( modelBaseName.c_str(), "head.", 5 ) == 0 ) { log_debug( "filename %s looks like a player model\n", modelBaseName.c_str() ); char value[20]; if ( model->getMetaData( "MD3_composite", value, sizeof( value ) ) ) { if ( atoi( value ) == 0 ) { log_debug( "model is explicitly not a composite\n" ); saveAsPlayer = false; } } else { // TODO: Eventually create a prompt instead of assuming "yes" log_debug( "model is implicitly a composite (no composite meta tag)\n" ); } } else { log_debug( "filename %s does not look like a player model\n", modelBaseName.c_str() ); saveAsPlayer = false; } } if ( saveAsPlayer ) { log_debug( "saving as a player model\n" ); std::string playerFile; std::string path = modelPath + "/"; playerFile = path + fixFileCase( m_modelPath.c_str(), "lower.md3" ); writeSectionFile( playerFile.c_str(), MS_Lower, meshes ); playerFile = path + fixFileCase( m_modelPath.c_str(), "upper.md3" ); writeSectionFile( playerFile.c_str(), MS_Upper, meshes ); playerFile = path + fixFileCase( m_modelPath.c_str(), "head.md3" ); writeSectionFile( playerFile.c_str(), MS_Head, meshes ); writeAnimations(); return Model::ERROR_NONE; } else { log_debug( "saving as a single model\n" ); return writeSectionFile( filename, MS_None, meshes ); } } else { log_error( "no filename supplied for model filter\n" ); return Model::ERROR_NO_FILE; } } Model::ModelErrorE Md3Filter::writeSectionFile( const char * filename, Md3Filter::MeshSectionE section, MeshList & meshes ) { string modelPath = ""; string modelBaseName = ""; string modelFullName = ""; log_debug( "writing section file %s\n", filename ); switch ( section ) { case MS_None: log_debug( " writing all data as one section\n" ); break; case MS_Lower: log_debug( " writing lower section\n" ); break; case MS_Upper: log_debug( " writing upper section\n" ); break; case MS_Head: log_debug( " writing head section\n" ); break; default: log_debug( " writing unknown section\n" ); break; } normalizePath( filename, modelFullName, modelPath, modelBaseName ); //MD3 HEADER int8_t magic[4]; magic[0] = 'I'; magic[1] = 'D'; magic[2] = 'P'; magic[3] = '3'; int32_t version = MD3_VERSION; char pk3Name[MAX_QPATH]; std::string pk3Path = ""; memset( pk3Name, 0, MAX_QPATH ); pk3Path = sectionToPath( section ); if ( !pk3Path.empty() && pk3Path[pk3Path.size() - 1] != '/' && pk3Path.size() < ( MAX_QPATH+1 ) ) { pk3Path += "/"; } if ( PORT_snprintf( pk3Name, sizeof( pk3Name ), "%s%s", pk3Path.c_str(), modelBaseName.c_str() ) >= MAX_QPATH ) { log_error( "MD3_PATH+filename is too large\n" ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "MD3_PATH+filename is to long." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } int32_t flags = 0; int32_t numFrames = 0; //We are making all the anims be one anim. unsigned animCount = m_model->getAnimCount( Model::ANIMMODE_FRAME ); for ( unsigned i = 0; i < animCount; i++ ) { // Skip animations that don't belong in this section std::string name = getSafeName( i ); if ( animInSection( name, section ) ) { numFrames += m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, i ); } } if ( numFrames > MD3_MAX_FRAMES ) { log_error( "Number of frames(%d) is larger than %d\n.\n", numFrames, MD3_MAX_FRAMES ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Too many animation frames for MD3 export." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } if ( animCount == 0 ) { animCount = 1; } if ( numFrames == 0 ) { numFrames = 1; } unsigned pcount = m_model->getPointCount(); int32_t numTags = (int32_t) pcount; switch ( section ) { case MS_Head: case MS_Lower: numTags = 1; break; case MS_Upper: numTags = 3; break; default: break; } MeshList::iterator mlit; int32_t numMeshes = 0; int numTris = 0; int numVerts = 0; std::string groupName; for ( mlit = meshes.begin(); mlit != meshes.end(); mlit++ ) { int g = (*mlit).group; // only grouped meshes are counted if ( g >= 0 ) { if ( groupInSection( m_model->getGroupName( (*mlit).group ), section ) ) { numMeshes++; numTris += (*mlit).faces.size(); numVerts += (*mlit).vertices.size(); } } } int32_t numSkins = 0; if ( numTags > MD3_MAX_TAGS ) { log_error( "Number of tags(%d) is larger than %d\n.\n", numTags, MD3_MAX_TAGS ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Too many points for MD3 export." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } if ( numMeshes > MD3_MAX_SURFACES ) { log_error( "Number of groups(%d) is larger than %d\n.\n", numMeshes, MD3_MAX_SURFACES ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Too many groups for MD3 export." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } // numSkins is usually zero for MD3 header, there can be skins for each mesh though later int32_t offsetFrames = HEADER_SIZE; int32_t offsetTags = offsetFrames + numFrames * FRAME_SIZE; int32_t offsetMeshes = offsetTags + numFrames * numTags * TAG_SIZE; int32_t offsetEnd = offsetMeshes; // MD3 limit tests if ( numTris > MD3_MAX_TRIANGLES ) { log_error( "Number of triangles(%d) is larger than %d\n.\n", numTris, MD3_MAX_TRIANGLES ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Too many faces in a single group for MD3 export" ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } if ( numVerts > MD3_MAX_VERTS ) { log_error( "Number of verticies(%d) is larger than %d\n.\n", numVerts, MD3_MAX_VERTS ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Too many vertices in a single group for MD3 export" ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } // Open file for writing Model::ModelErrorE err = Model::ERROR_NONE; m_dst = openOutput( filename, err ); FunctionCaller fc( m_dst, &DataDest::close ); if ( err != Model::ERROR_NONE ) return err; // write file header m_dst->write( magic[0] ); m_dst->write( magic[1] ); m_dst->write( magic[2] ); m_dst->write( magic[3] ); m_dst->write( version ); m_dst->writeBytes( (uint8_t*) pk3Name, MAX_QPATH ); m_dst->write( flags ); m_dst->write( numFrames ); m_dst->write( numTags ); m_dst->write( numMeshes ); m_dst->write( numSkins ); m_dst->write( offsetFrames ); m_dst->write( offsetTags ); m_dst->write( offsetMeshes ); uint32_t endPos = m_dst->offset(); m_dst->write( offsetEnd ); int rootTag = -1; // Change save matrix if needed log_debug( "finding root tag for section %s\n", modelBaseName.c_str() ); for ( unsigned p = 0; p < pcount; p++ ) { if ( tagIsSectionRoot( m_model->getPointName( p ), section ) ) { log_debug( " root tag is %s\n", m_model->getPointName( p ) ); rootTag = p; } } // FRAMES log_debug( "writing frames at %d/%d\n", offsetFrames, m_dst->offset() ); unsigned a; for ( a = 0; a < animCount; a++ ) { if ( animInSection( getSafeName( a ), section ) || (section == MS_Head && a == 0) ) { unsigned aFrameCount = m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, a ); if ( (aFrameCount == 0 && animCount == 1 ) || (section == MS_Head) ) { aFrameCount = 1; } for ( unsigned t = 0; t < aFrameCount; t++ ) { Matrix saveMatrix = getMatrixFromPoint( a, t, rootTag ).getInverse(); list::iterator vit; double max[4] = { DBL_MIN, DBL_MIN, DBL_MIN, 1 }; double min[4] = { DBL_MAX, DBL_MAX, DBL_MAX, 1 }; for ( mlit = meshes.begin(); mlit != meshes.end(); mlit++ ) { int i = (*mlit).group; if ( i >= 0 && groupInSection( m_model->getGroupName( i ), section ) ) { list tris = m_model->getGroupTriangles( i ); list::iterator it; for ( it = tris.begin(); it != tris.end(); it++ ) { for ( int n = 0; n < 3; n++ ) { int vertex = m_model->getTriangleVertex( *it, n ); double cords[3]; m_model->getFrameAnimVertexCoords( a, t, vertex, cords[0], cords[1], cords[2] ); max[0] = greater( max[0], cords[0] ); max[1] = greater( max[1], cords[1] ); max[2] = greater( max[2], cords[2] ); min[0] = smaller( min[0], cords[0] ); min[1] = smaller( min[1], cords[1] ); min[2] = smaller( min[2], cords[2] ); } } } } saveMatrix.apply( min ); saveMatrix.apply( max ); //min_bounds for ( int v = 0; v < 3; v++ ) { m_dst->write( (float) min[v] ); } //max_bounds for ( int v = 0; v < 3; v++ ) { m_dst->write( (float) max[v] ); } //local_origin float temp = 0; for ( int v = 0; v < 3; v++ ) { m_dst->write( temp ); } //radius double radiusm = sqrt( min[0] * min[0] + min[1] * min[1] + min[2] * min[2] ); double radius = sqrt( max[0] * max[0] + max[1] * max[1] + max[2] * max[2] ); if ( radiusm > radius ) { radius = radiusm; } //log_debug( "Frame radius: %f\n", ( (float) radius ) ); m_dst->write( (float) radius ); char name[16] = "Misfit Model 3D"; // this is what other exporters do m_dst->writeBytes( (uint8_t*) name, 16 ); } } } //TAGS log_debug( "writing tags at %d/%d\n", offsetTags, m_dst->offset() ); for ( a = 0; a < animCount; a++ ) { if ( animInSection( getSafeName( a ), section ) || (section == MS_Head && a == 0) ) { unsigned aFrameCount = m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, a ); if ( (aFrameCount == 0 && animCount == 1) || (section == MS_Head) ) { aFrameCount = 1; } for ( unsigned t = 0; t < aFrameCount; t++ ) { Matrix saveMatrix = getMatrixFromPoint( a, t, rootTag ).getInverse(); for ( unsigned j = 0; j < pcount; j++ ) { if ( tagInSection( m_model->getPointName( j ), section ) ) { char tName[MAX_QPATH]; memset( tName, 0, MAX_QPATH ); if ( PORT_snprintf( tName, sizeof( tName ), "%s", m_model->getPointName( j ) ) >= MAX_QPATH ) { log_error( "Point name is too large\n" ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Point name is too large for MD3 export." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } m_dst->writeBytes( (uint8_t*) tName, MAX_QPATH ); // origin double origin[4] = { 0, 0, 0, 1 }; m_model->getFrameAnimPointCoords( a, t, j, origin[0], origin[1], origin[2] ); saveMatrix.apply( origin ); m_dst->write( (float) origin[0] ); m_dst->write( (float) origin[1] ); m_dst->write( (float) origin[2] ); Matrix rotMatrix; double rotVector[3]; m_model->getFrameAnimPointRotation( a, t, j, rotVector[0], rotVector[1], rotVector[2] ); // Seems whenver we have a nan its from a identity matrix if ( rotVector[0] != rotVector[0] || rotVector[1] != rotVector[1] || rotVector[2] != rotVector[2] ) { writeIdentity(); continue; } rotMatrix.setRotation( rotVector ); rotMatrix = rotMatrix*saveMatrix; // orientation for ( int m = 0; m < 3; m++ ) { for ( int n = 0; n < 3; n++ ) { m_dst->write( (float) rotMatrix.get( m, n ) ); } } } } } } } vector & modelMaterials = getMaterialList( m_model ); // MESHES log_debug( "writing meshes at %d/%d\n", offsetMeshes, m_dst->offset() ); for ( mlit = meshes.begin(); mlit != meshes.end(); mlit++ ) { if ( (*mlit).group >= 0 && groupInSection( m_model->getGroupName( (*mlit).group ), section ) ) { // MESH HEADER int8_t mMagic[4]; mMagic[0] = 'I'; mMagic[1] = 'D'; mMagic[2] = 'P'; mMagic[3] = '3'; char mName[MAX_QPATH]; memset( mName, 0, MAX_QPATH ); if ( PORT_snprintf( mName, sizeof( mName ), "%s", m_model->getGroupName( (*mlit).group ) ) > MAX_QPATH ) { log_error( "group name is too large\n" ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Group name is too large for MD3 export." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } const int TRI_SIZE = 3 * 4; const int SHADER_SIZE = MAX_QPATH + 4; const int TEXCOORD_SIZE = 2 * 4; const int VERT_SIZE = 4 * 2; int32_t mFlags = 0; int32_t mNumFrames = numFrames; int32_t mNumShaders = 1; int32_t mNumVerts = (*mlit).vertices.size(); int32_t mNumTris = (*mlit).faces.size(); int32_t mOffTris = HEADER_SIZE; int32_t mOffShaders = mOffTris + mNumTris * TRI_SIZE; int32_t mOffST = mOffShaders + mNumShaders * SHADER_SIZE; int32_t mOffVerts = mOffST + mNumVerts * TEXCOORD_SIZE; int32_t mOffEnd = mOffVerts + mNumFrames * mNumVerts * VERT_SIZE; // write header m_dst->write( mMagic[0] ); m_dst->write( mMagic[1] ); m_dst->write( mMagic[2] ); m_dst->write( mMagic[3] ); m_dst->writeBytes( (uint8_t*) mName, MAX_QPATH ); m_dst->write( mFlags ); m_dst->write( mNumFrames ); m_dst->write( mNumShaders ); m_dst->write( mNumVerts ); m_dst->write( mNumTris ); m_dst->write( mOffTris ); m_dst->write( mOffShaders ); m_dst->write( mOffST ); m_dst->write( mOffVerts ); m_dst->write( mOffEnd ); // TRIANGLES Mesh::FaceList::iterator fit; for ( fit = (*mlit).faces.begin(); fit != (*mlit).faces.end(); fit++ ) { for ( int j = 2; j >= 0; j-- ) { m_dst->write( (*fit).v[j] ); } } // SHADERS for ( int32_t t = 0; t < mNumShaders; t++ ) { int matId = m_model->getGroupTextureId( (*mlit).group ); string matFileName; string matFullName; string matPath; string matBaseName; if ( matId != -1 ) { Model::Material * mat = modelMaterials[matId]; matFileName = mat->m_filename; } else { //Texture isn't set matFileName = mName; matFileName += ".tga"; } char sName[MAX_QPATH]; std::string spk3Path; memset( sName, 0, MAX_QPATH ); if ( matId >= 0 ) { spk3Path = materialToPath( matId ); if ( !spk3Path.empty() && spk3Path[spk3Path.size() - 1] != '/' && spk3Path.size() < ( MAX_QPATH+1 ) ) { spk3Path += "/"; } } normalizePath( matFileName.c_str(), matFullName, matPath, matBaseName ); log_debug( "comparing %s and %s\n", matFullName.c_str(), m_modelPath.c_str() ); if ( strncmp( matFullName.c_str(), m_modelPath.c_str(), m_modelPath.size() ) == 0) { log_debug( "path is common, using MD3_PATH\n" ); // model path is the same as texture file path, remove model // path and prepend MD3_PATH if ( PORT_snprintf( sName, sizeof( sName ), "%s%s", spk3Path.c_str(), matBaseName.c_str() ) >= MAX_QPATH ) { log_error( "MD3_PATH+texture_filename is to long.\n" ); m_model->setFilterSpecificError( transll( QT_TRANSLATE_NOOP( "LowLevel", "Texture filename is too long." ) ).c_str() ); return Model::ERROR_FILTER_SPECIFIC; } } else if ( pathIsAbsolute( matFileName.c_str() ) ) { log_debug( "path is not common, but is absolute\n" ); // model path is not the same as texture file path, try to // remove pk3 path from model and try again std::string common; common = m_modelPath; // default to PK3 Path PORT_snprintf( sName, sizeof( sName ), "%s%s", spk3Path.c_str(), matBaseName.c_str() ); } else { log_debug( "path is relative, using as-is\n" ); // relative path... sounds like a fallback, just use // matFileName as is PORT_snprintf( sName, sizeof(sName), "%s", matFileName.c_str() ); } log_debug( "writing texture path: %s\n", sName ); m_dst->writeBytes( (uint8_t*) sName, MAX_QPATH ); m_dst->write( t ); } // TEXT COORDS Mesh::VertexList::iterator vit; for ( vit = (*mlit).vertices.begin(); vit != (*mlit).vertices.end(); vit++ ) { m_dst->write( (*vit).uv[0] ); m_dst->write( (float) (1.0f - (*vit).uv[1]) ); } // VERTEX m_model->calculateNormals(); for ( unsigned a = 0; a < animCount; a++ ) { if ( animInSection( getSafeName( a ), section ) || (section == MS_Head && a == 0) ) { // If there are no anims calculateFrameNormals will segfault // (in earlier versions of MM3D) if ( m_model->getAnimCount( Model::ANIMMODE_FRAME ) > 0 ) { m_model->calculateFrameNormals( a ); } unsigned aFrameCount = m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, a ); if ( (aFrameCount == 0 && animCount == 1) || (section == MS_Head) ) { aFrameCount = 1; } for ( unsigned t = 0; t < aFrameCount; t++ ) { Matrix saveMatrix = getMatrixFromPoint( a, t, rootTag ).getInverse(); if ( section == MS_Head ) { saveMatrix = getMatrixFromPoint( -1, -1, rootTag ).getInverse(); } for ( vit = (*mlit).vertices.begin(); vit != (*mlit).vertices.end(); vit++ ) { double meshVec[4] = {0,0,0,1}; double meshNor[4] = {0,0,0,1}; if ( section == MS_Head ) { // force unanimated coordinates for head m_model->getVertexCoords( (*vit).v, meshVec ); } else { //getFrameAnimVertexCoords will get non frame coords if no anim m_model->getFrameAnimVertexCoords( a, t, (*vit).v, meshVec[0], meshVec[1], meshVec[2] ); } if ( aFrameCount == 1 && animCount == 1 ) { float meshNorF[3]; if ( getVertexNormal( m_model, (*mlit).group, (*vit).v, meshNorF ) ) { meshNor[0] = meshNorF[0]; meshNor[1] = meshNorF[1]; meshNor[2] = meshNorF[2]; } } else { m_model->getFrameAnimVertexNormal( a, t, (*vit).v, meshNor[0], meshNor[1], meshNor[2] ); } saveMatrix.apply( meshVec ); saveMatrix.apply( meshNor ); m_dst->write( (int16_t) ( meshVec[0] / MD3_XYZ_SCALE + 0.5 ) ); m_dst->write( (int16_t) ( meshVec[1] / MD3_XYZ_SCALE + 0.5 ) ); m_dst->write( (int16_t) ( meshVec[2] / MD3_XYZ_SCALE + 0.5 ) ); int16_t lng; int16_t lat; if ( meshNor[0] == 0 && meshNor[1] == 0 ) { if ( meshNor[2] > 0 ) { lng = 0; lat = 0; } else { lat = 128; lng = 0; } } else { lng = (int16_t) ( acos( meshNor[2] ) * 255 / ( 2 * PI ) ); lat = (int16_t) ( atan2( meshNor[1], meshNor[0] ) * 255 / ( 2 * PI ) ); } // log_debug("%f, %f, %f lat %d lng %d\n", meshNor[0], meshNor[1], meshNor[2], lat, lng); uint16_t normal = ( ( lat & 255 ) * 256 ) | ( lng & 255 ); m_dst->write( normal ); } } } } } } offsetEnd = m_dst->offset(); m_dst->seek( endPos ); m_dst->write( offsetEnd ); return Model::ERROR_NONE; } bool Md3Filter::writeAnimations() { string animFile = m_modelPath + "/animation.cfg"; FILE * fp = fopen( animFile.c_str(), "w" ); if ( fp != NULL ) { log_debug( "writing animation.cfg\n" ); fprintf( fp, "// animation config file\r\n\r\n" ); char value[30]; if ( m_model->getMetaData( "MD3_sex", value, sizeof(value) ) ) { fprintf( fp, "sex %s\r\n", value ); } if ( m_model->getMetaData( "MD3_footsteps", value, sizeof(value) ) ) { fprintf( fp, "footsteps %s\r\n", value ); } if ( m_model->getMetaData( "MD3_headoffset", value, sizeof(value) ) ) { fprintf( fp, "headoffset %s\r\n", value ); } if ( m_model->getMetaData( "MD3_fixedtorso", value, sizeof(value) ) ) { fprintf( fp, "fixedtorso %s\r\n", value ); } if ( m_model->getMetaData( "MD3_fixedlegs", value, sizeof(value) ) ) { fprintf( fp, "fixedlegs %s\r\n", value ); } fprintf( fp, "\r\n" ); fprintf( fp, "// frame data:\r\n" ); fprintf( fp, "// first count looping fps\r\n\r\n" ); char warning[] = " (MUST NOT CHANGE -- hand animation is synced to this)"; for ( int anim = 0; anim < MD3_ANIMATIONS; anim++ ) { int animIndex = 0; int animFrame = 0; int count = 1; int fps = 15; getExportAnimData( anim, animIndex, animFrame, count, fps ); int loop = count; // loop by default // disable looping on non-looping anims if ( count <= 1 || s_animLoop[anim] == 0 ) { loop = 0; } char name[30]; strcpy( name, s_animNames[anim] ); size_t len = strlen( name ); for ( size_t n = 0; n < len; n++ ) { name[n] = toupper( name[n] ); } fprintf( fp, "%d\t%d\t%d\t%d\t\t// %s%s\r\n", animFrame, count, loop, fps, name, (s_animSyncWarning[anim] ? warning : "") ); } fclose( fp ); return true; } return false; } Matrix Md3Filter::getMatrixFromPoint( int anim, int frame, int point ) { Matrix m; m.loadIdentity(); if ( point < 0 ) { m.setRotationInDegrees( -90, -90, 0 ); return m; } double rot[3]; double pos[3]; if ( anim >= 0 && frame >= 0 ) { m_model->getFrameAnimPointRotation( anim, frame, point, rot[0], rot[1], rot[2] ); m_model->getFrameAnimPointCoords( anim, frame, point, pos[0], pos[1], pos[2] ); } else { m_model->getPointRotation( point, rot ); m_model->getPointTranslation( point, pos ); } m.loadIdentity(); m.setRotation( rot ); m.setTranslation( pos ); return m; } void Md3Filter::getExportAnimData( int fileAnim, int & modelAnim, int & fileFrame, int & frameCount, int & fps ) { fileFrame = 0; frameCount = 0; size_t animCount = m_model->getAnimCount( Model::ANIMMODE_FRAME ); for ( size_t a = 0; a < animCount; a++ ) { std::string name = getSafeName( a ); if ( animInSection( name, MS_Upper ) || animInSection( name, MS_Lower ) ) { if ( strcasecmp( s_animNames[ fileAnim ], name.c_str() ) == 0 ) { frameCount = m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, a ); fps = (int) m_model->getAnimFPS( Model::ANIMMODE_FRAME, a ); if ( fps <= 0 ) // just being paranoid { fps = 15; } return; } else { fileFrame += m_model->getAnimFrameCount( Model::ANIMMODE_FRAME, a ); } } } // if this is a "dead" animation and there isn't a "dead" animation, try the // last frame of the "death" animation. if ( fileAnim < 6 && (fileAnim % 2) == 1 ) { fileAnim--; getExportAnimData( fileAnim, modelAnim, fileFrame, frameCount, fps ); if ( modelAnim >= 0 ) { fileFrame += frameCount - 1; frameCount = 1; return; } } modelAnim = -1; } size_t Md3Filter::writeIdentity() { size_t count = 0; float z = 0.0; float o = 1.0; for ( int i = 0; i < 3; i++ ) { for ( int j = 0; j < 3; j++ ) { if ( i == j ) { count += m_dst->write( o ); } else { count += m_dst->write( z ); } } } return count; } std::string Md3Filter::extractPath( const char * md3DataPath ) { std::string path = md3DataPath; replaceBackslash( path ); size_t i = path.rfind( '/' ); if ( i > 0 && i < path.size() ) { path.resize( i + 1 ); return path; } else { return ""; } } std::string Md3Filter::sectionToPath( int materialIndex ) { char pk3Path[MAX_QPATH] = ""; if ( m_model->getMetaData( "MD3_PATH", pk3Path, sizeof(pk3Path) ) ) { return pk3Path; } // NOTE: I removed the "model/" stuff because it's causing problems with // working models return ""; } std::string Md3Filter::materialToPath( int materialIndex ) { char pk3Path[MAX_QPATH] = ""; const char * name = m_model->getTextureName( materialIndex ); if ( !name ) { name = ""; } log_debug( "getting path for material %d: %s\n", materialIndex, name ); std::string keyStr = std::string("MD3_PATH_") + name; if ( m_model->getMetaData( keyStr.c_str(), pk3Path, sizeof(pk3Path) ) ) { log_debug( " material-specific: %s\n", pk3Path ); return pk3Path; } keyStr = "MD3_PATH"; if ( m_model->getMetaData( keyStr.c_str(), pk3Path, sizeof(pk3Path) ) ) { log_debug( " default: %s\n", pk3Path ); return pk3Path; } return ""; } std::string Md3Filter::defaultPath() { std::string path = "models/players/"; std::string modelName = "noname/"; if ( m_modelPath.size() > 1 ) { size_t i = m_modelPath.rfind( '/', m_modelPath.size()-2 ); if ( i > 0 && i < m_modelPath.size() ) { modelName = m_modelPath.substr( i+1, m_modelPath.size() ); } } path += modelName; return path; } //returns greater of a or b double Md3Filter::greater( double a, double b ) { if ( a > b ) { return a; } return b; } //returns smaller of a or b double Md3Filter::smaller( double a, double b ) { if ( a < b ) { return a; } return b; } bool Md3Filter::getVertexNormal( Model * model, int groupId, int vertexId, float *normal ) { list tris = model->getGroupTriangles( groupId ); list::iterator tri; for ( tri = tris.begin(); tri != tris.end(); tri++ ) { for ( int n = 0; n < 3; n++ ) { int vert = model->getTriangleVertex( *tri, n ); if ( vert == vertexId ) { model->getNormal( *tri, n, normal ); return true; } } } return false; } //MM3D internal stuff bool Md3Filter::canRead( const char * filename ) { log_debug( "canRead( %s )\n", filename ); log_debug( " true\n" ); return true; } bool Md3Filter::canWrite( const char * filename ) { log_debug( "canWrite( %s )\n", filename ); log_debug( " true\n" ); return true; } bool Md3Filter::canExport( const char * filename ) { log_debug( "canExport( %s )\n", filename ); log_debug( " true\n" ); return true; } bool Md3Filter::isSupported( const char * filename ) { log_debug( "isSupported( %s )\n", filename ); unsigned len = strlen( filename ); if ( len >= 4 && strcasecmp( &filename[len-4], ".md3" ) == 0 ) { log_debug( " true\n" ); return true; } else { log_debug( " false\n" ); return false; } } list< string > Md3Filter::getReadTypes() { list rval; rval.push_back( "*.md3" ); return rval; } list< string > Md3Filter::getWriteTypes() { list rval; rval.push_back( "*.md3" ); return rval; } #ifdef PLUGIN //------------------------------------------------------------------ // Plugin functions //------------------------------------------------------------------ PLUGIN_API bool plugin_init() { if ( s_filter == NULL ) { s_filter = new Md3Filter(); FilterManager * texmgr = FilterManager::getInstance(); texmgr->registerFilter( s_filter ); } log_debug( "MD3 model filter plugin initialized\n" ); return true; } // The filter manager will delete our registered filter. // We have no other cleanup to do PLUGIN_API bool plugin_uninit() { s_filter = NULL; // FilterManager deletes filters log_debug( "MD3 model filter plugin uninitialized\n" ); return true; } PLUGIN_API const char * plugin_version() { return "0.1.0"; } PLUGIN_API const char * plugin_mm3d_version() { return VERSION_STRING; } PLUGIN_API const char * plugin_desc() { return "MD3 model filter"; } #endif // PLUGIN mm3d-1.3.7/src/libmm3d/bsptree.h0000644000175000017500000000612210744511346013244 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __BSPTREE_H #define __BSPTREE_H #include "drawcontext.h" #include class BspTree { public: class Poly { public: static Poly * get(); void release(); static int flush(); static void stats(); int id; float coord[3][3]; float drawNormals[3][3]; int texture; void * material; // Yeah, yeah, I know... it's hackish float s[3]; // texture coordinates float t[3]; float norm[3]; float d; // dot product void calculateNormal(); void calculateD(); void intersection( float * p1, float * p2, float * po, float & place ); void render( DrawingContext * context ); void print(); protected: Poly() : id( ++s_nextId ) { s_allocated++; }; virtual ~Poly() { s_allocated--; }; static int s_nextId; static std::list< Poly * > s_recycle; static int s_allocated; }; class Node { public: static Node * get(); void release(); static int flush(); static void stats(); void addChild( Node * n ); void render( float * point, DrawingContext * context ); void splitNodes( int idx1, int idx2, int idx3, float * p1, float * p2, Node * n1, Node * n2, const float & place1, const float & place2 ); void splitNode( int idx1, int idx2, int idx3, float * p1, Node * n1, const float & place ); Poly * self; Node * left; Node * right; protected: Node() : self( NULL ), left( NULL ), right( NULL ) { s_allocated++;}; virtual ~Node() { s_allocated--; }; static std::list< Node * > s_recycle; static int s_allocated; }; BspTree() : m_root( NULL ) {}; virtual ~BspTree() { clear(); }; void addPoly( Poly * p ); void render( float * point, DrawingContext * context ); void clear(); protected: Node * m_root; }; #endif // __BSPTREE_H mm3d-1.3.7/src/libmm3d/tgatex.h0000644000175000017500000000400010744511346013065 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef __TGATEX_H #define __TGATEX_H #include #include #include "texmgr.h" class TgaTextureFilter : public TextureFilter { public: TgaTextureFilter(); virtual ~TgaTextureFilter(); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); Texture::ErrorE readFile( Texture * texture, const char * filename ); virtual bool canRead( const char * filename ); protected: std::list< std::string > m_read; std::list< std::string > m_write; }; class OldTgaTextureFilter : public TextureFilter { public: OldTgaTextureFilter(); virtual ~OldTgaTextureFilter(); std::list< std::string > getReadTypes(); std::list< std::string > getWriteTypes(); Texture::ErrorE readFile( Texture * texture, const char * filename ); virtual bool canRead( const char * filename ); static void read( uint8_t & val, FILE * fp ); static void read( uint16_t & val, FILE * fp ); static void readBytes( void * buf, size_t len, FILE * fp ); protected: std::list< std::string > m_read; std::list< std::string > m_write; }; #endif // TGATEX_H mm3d-1.3.7/src/libmm3d/filefactory.cc0000644000175000017500000000357110744511346014252 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2007 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #include "filefactory.h" #include "datadest.h" #include "datasource.h" #include "filedatadest.h" #include "filedatasource.h" FileFactory::FileFactory() { } FileFactory::~FileFactory() { closeAll(); } void FileFactory::closeAll() { for ( SourceMap::iterator it = m_sources.begin(); it != m_sources.end(); ++it ) { delete it->second; } m_sources.clear(); for ( DestMap::iterator it = m_dests.begin(); it != m_dests.end(); ++it ) { delete it->second; } m_dests.clear(); } DataDest * FileFactory::getDest( const char * filename ) { DataDest * dst = createDest( filename ); m_dests[filename] = dst; return dst; } DataSource * FileFactory::getSource( const char * filename ) { DataSource * dst = createSource( filename ); m_sources[filename] = dst; return dst; } DataDest * FileFactory::createDest( const char * filename ) { return new FileDataDest( filename ); } DataSource * FileFactory::createSource( const char * filename ) { return new FileDataSource( filename ); } mm3d-1.3.7/src/libmm3d/cmdlinemgr.h0000644000175000017500000000664010744511346013726 00000000000000/* Misfit Model 3D * * Copyright (c) 2004-2008 Kevin Worcester * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * See the COPYING file for full license text. */ #ifndef CMDLINEMGR_H_INC__ #define CMDLINEMGR_H_INC__ #include #include #include "local_ptr.h" class CommandLineManager { public: class Option { public: Option( char shortOption, const char * longOption = NULL, const char * defaultValue = NULL, bool takesArg = false ); virtual ~Option(); char shortOption() const { return m_shortOption; } const char * longOption() const { return m_longOption; } bool takesArgument() const { return m_takesArg; } void parseOption(const char * arg); int intValue() const { return m_intValue; } const char * stringValue() const { return m_stringValue.c_str(); } bool isSpecified() const { return m_isSpecified; } protected: void setIntValue(int val) { m_intValue = val; } void setStringValue(const char * val) { m_stringValue = val; } virtual void customParse(const char * arg); private: char m_shortOption; const char * m_longOption; bool m_takesArg; bool m_isSpecified; int m_intValue; std::string m_stringValue; }; enum ErrorE { NoError, UnknownOption, MissingArgument, }; typedef void (*OptionFunctionF)(const char *); CommandLineManager(); virtual ~CommandLineManager(); bool parse( int argc, const char ** argv ); int firstArgument() const { return m_firstArg; } ErrorE error() const { return m_error; } int errorArgument() const { return m_errorArg; } void addOption( int id, char shortOption, const char * longOption = NULL, const char * defaultValue = NULL, bool takesArg = false ); void addCustomOption( int id, Option * opt ); void addFunctionOption( int id, char shortOption, const char * longOption, bool takesArg, OptionFunctionF optFunc ); bool isSpecified( int optionId ) const; int intValue( int optionId ) const; const char * stringValue( int optionId ) const; int getUniqueId(); private: typedef std::map< int, local_ptr