mirror of
https://github.com/panda3d/panda3d.git
synced 2026-02-14 19:18:51 -06:00
Initial revision
This commit is contained in:
49
panda/Config.Irix.pp
Normal file
49
panda/Config.Irix.pp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Config.Irix.pp
|
||||
//
|
||||
// This file defines some custom config variables for the SGI/Irix
|
||||
// platform. It makes some initial guesses about compiler features,
|
||||
// etc.
|
||||
//
|
||||
|
||||
// Is the platform big-endian (like an SGI workstation) or
|
||||
// little-endian (like a PC)? Define this to the empty string to
|
||||
// indicate little-endian, or nonempty to indicate big-endian.
|
||||
#define WORDS_BIGENDIAN 1
|
||||
|
||||
// Does the C++ compiler support namespaces?
|
||||
#define HAVE_NAMESPACE 1
|
||||
|
||||
// Does the C++ compiler support ios::binary?
|
||||
#define HAVE_IOS_BINARY
|
||||
|
||||
// Do we have a gettimeofday() function?
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
// Does gettimeofday() take only one parameter?
|
||||
#define GETTIMEOFDAY_ONE_PARAM
|
||||
|
||||
// Do we have getopt() and/or getopt_long_only() built into the
|
||||
// system?
|
||||
#define HAVE_GETOPT 1
|
||||
#define HAVE_GETOPT_LONG_ONLY
|
||||
|
||||
// Should we include <iostream> or <iostream.h>? Define HAVE_IOSTREAM
|
||||
// to nonempty if we should use <iostream>, or empty if we should use
|
||||
// <iostream.h>.
|
||||
#define HAVE_IOSTREAM
|
||||
|
||||
// Do we have a true stringstream class defined in <sstream>?
|
||||
#define HAVE_SSTREAM
|
||||
|
||||
// Do we have <malloc.h>?
|
||||
#define HAVE_MALLOC_H 1
|
||||
|
||||
// Do we have <alloca.h>?
|
||||
#define HAVE_ALLOCA_H 1
|
||||
|
||||
// Do we have <sys/types.h>?
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
// Do we have <unistd.h>?
|
||||
#define HAVE_UNISTD_H 1
|
||||
49
panda/Config.Linux.pp
Normal file
49
panda/Config.Linux.pp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Config.Linux.pp
|
||||
//
|
||||
// This file defines some custom config variables for the Linux
|
||||
// platform. It makes some initial guesses about compiler features,
|
||||
// etc.
|
||||
//
|
||||
|
||||
// Is the platform big-endian (like an SGI workstation) or
|
||||
// little-endian (like a PC)? Define this to the empty string to
|
||||
// indicate little-endian, or nonempty to indicate big-endian.
|
||||
#define WORDS_BIGENDIAN
|
||||
|
||||
// Does the C++ compiler support namespaces?
|
||||
#define HAVE_NAMESPACE 1
|
||||
|
||||
// Does the C++ compiler support ios::binary?
|
||||
#define HAVE_IOS_BINARY 1
|
||||
|
||||
// Do we have a gettimeofday() function?
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
// Does gettimeofday() take only one parameter?
|
||||
#define GETTIMEOFDAY_ONE_PARAM
|
||||
|
||||
// Do we have getopt() and/or getopt_long_only() built into the
|
||||
// system?
|
||||
#define HAVE_GETOPT 1
|
||||
#define HAVE_GETOPT_LONG_ONLY 1
|
||||
|
||||
// Should we include <iostream> or <iostream.h>? Define HAVE_IOSTREAM
|
||||
// to nonempty if we should use <iostream>, or empty if we should use
|
||||
// <iostream.h>.
|
||||
#define HAVE_IOSTREAM
|
||||
|
||||
// Do we have a true stringstream class defined in <sstream>?
|
||||
#define HAVE_SSTREAM
|
||||
|
||||
// Do we have <malloc.h>?
|
||||
#define HAVE_MALLOC_H 1
|
||||
|
||||
// Do we have <alloca.h>?
|
||||
#define HAVE_ALLOCA_H 1
|
||||
|
||||
// Do we have <sys/types.h>?
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
// Do we have <unistd.h>?
|
||||
#define HAVE_UNISTD_H 1
|
||||
49
panda/Config.Win32.pp
Normal file
49
panda/Config.Win32.pp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Config.Win32.pp
|
||||
//
|
||||
// This file defines some custom config variables for the Windows
|
||||
// platform. It makes some initial guesses about compiler features,
|
||||
// etc.
|
||||
//
|
||||
|
||||
// Is the platform big-endian (like an SGI workstation) or
|
||||
// little-endian (like a PC)? Define this to the empty string to
|
||||
// indicate little-endian, or nonempty to indicate big-endian.
|
||||
#define WORDS_BIGENDIAN
|
||||
|
||||
// Does the C++ compiler support namespaces?
|
||||
#define HAVE_NAMESPACE 1
|
||||
|
||||
// Does the C++ compiler support ios::binary?
|
||||
#define HAVE_IOS_BINARY 1
|
||||
|
||||
// Do we have a gettimeofday() function?
|
||||
#define HAVE_GETTIMEOFDAY
|
||||
|
||||
// Does gettimeofday() take only one parameter?
|
||||
#define GETTIMEOFDAY_ONE_PARAM
|
||||
|
||||
// Do we have getopt() and/or getopt_long_only() built into the
|
||||
// system?
|
||||
#define HAVE_GETOPT
|
||||
#define HAVE_GETOPT_LONG_ONLY
|
||||
|
||||
// Should we include <iostream> or <iostream.h>? Define HAVE_IOSTREAM
|
||||
// to nonempty if we should use <iostream>, or empty if we should use
|
||||
// <iostream.h>.
|
||||
#define HAVE_IOSTREAM 1
|
||||
|
||||
// Do we have a true stringstream class defined in <sstream>?
|
||||
#define HAVE_SSTREAM 1
|
||||
|
||||
// Do we have <malloc.h>?
|
||||
#define HAVE_MALLOC_H 1
|
||||
|
||||
// Do we have <alloca.h>?
|
||||
#define HAVE_ALLOCA_H
|
||||
|
||||
// Do we have <sys/types.h>?
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
// Do we have <unistd.h>?
|
||||
#define HAVE_UNISTD_H
|
||||
167
panda/Config.pp
Normal file
167
panda/Config.pp
Normal file
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// Config.pp
|
||||
//
|
||||
// This file defines certain configuration variables that are written
|
||||
// into the various make scripts. It is processed by ppremake (along
|
||||
// with the Sources.pp files in each of the various directories) to
|
||||
// generate build scripts appropriate to each environment.
|
||||
//
|
||||
// ppremake is capable of generating generic Unix autoconf/automake
|
||||
// style build scripts, as well as makefiles customized for SGI's
|
||||
// MipsPRO compiler or for Microsoft's Visual C++. It can also
|
||||
// generate Microsoft Developer's Studio project files directly. In
|
||||
// principle, it can be extended to generate suitable build script
|
||||
// files for any number of different build environments.
|
||||
//
|
||||
// All of these build scripts can be tuned for a particular
|
||||
// environment via this file. This is the place for the user to
|
||||
// specify which external packages are installed and where, or to
|
||||
// enable or disable certain optional features. However, it is
|
||||
// suggested that rather than modify this file directly, you create a
|
||||
// custom file in your home directory and there redefine whatever
|
||||
// variables are appropriate, and set the environment variable
|
||||
// PPREMAKE_CONFIG to refer to it. In this way, you can easily get an
|
||||
// updated source tree (including a new Config.pp) without risking
|
||||
// accidentally losing your customizations. This also avoids having
|
||||
// to redefine the same variables in different packages (for instance,
|
||||
// in dtool and in panda).
|
||||
//
|
||||
// If you *do* decide to make changes directly to this file, you
|
||||
// should also comment out the line near the bottom that includes the
|
||||
// file $[TOPDIRPREFIX]Config.$[PLATFORM].pp, to avoid stomping on the
|
||||
// changes you make.
|
||||
//
|
||||
// The syntax in this file resembles some hybrid between C++
|
||||
// preprocessor declarations and GNU make variables. This is the same
|
||||
// syntax used in the various ppremake system configure files; it's
|
||||
// designed to be easy to use as a macro language to generate
|
||||
// makefiles and their ilk.
|
||||
//
|
||||
|
||||
// What kind of build scripts are we generating? This selects a
|
||||
// suitable template file from the ppremake system files. The
|
||||
// allowable choices, at present, are:
|
||||
//
|
||||
// autoconf - Generate configure.in and a series of Makefile.am files,
|
||||
// suitable for using with autoconf/automake. Not quite
|
||||
// there yet.
|
||||
// stopgap - Generate original Cary-style Makefile/Makefile.install/etc.
|
||||
// files, to ease transition to the new system.
|
||||
//
|
||||
#define BUILD_TYPE stopgap
|
||||
|
||||
// Define the directory in which the system ppremake files are
|
||||
// installed.
|
||||
#define PPREMAKE_DIR /usr/local/panda/share
|
||||
|
||||
|
||||
// In which directory should this package be installed when you type
|
||||
// "make install"? This has no meaning when BUILD_TYPE is "stopgap".
|
||||
#define INSTALL_DIR /usr/local/panda
|
||||
|
||||
|
||||
// What level of compiler optimization/debug symbols should we build?
|
||||
// The various optimize levels are defined as follows:
|
||||
//
|
||||
// 1 - No compiler optimizations, full debug symbols
|
||||
// 2 - Full compiler optimizations, full debug symbols
|
||||
// (if the compiler supports this)
|
||||
// 3 - Full compiler optimizations, no debug symbols
|
||||
// 4 - Full optimizations, no debug symbols, and asserts removed
|
||||
//
|
||||
// Setting this has no effect when BUILD_TYPE is "stopgap". In this
|
||||
// case, the compiler optimizations are selected by setting the
|
||||
// environment variable OPTIMIZE accordingly at compile time.
|
||||
#define OPTIMIZE 1
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// The remaining variables are considered only if BUILD_TYPE is not
|
||||
// "autoconf". (Autoconf can determine these directly.)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// NOTE: In the following, to indicate "yes" to a yes/no question,
|
||||
// define the variable to be a nonempty string. To indicate "no",
|
||||
// define the variable to be an empty string.
|
||||
|
||||
// Is Python installed, and should Python interfaces be generated? If
|
||||
// Python is installed, which directory is it in? (If the directory
|
||||
// is someplace standard like /usr/include, you may leave it blank.)
|
||||
#define HAVE_PYTHON 1
|
||||
#define PYTHON_INCLUDE /usr/local/include/python1.6
|
||||
#define PYTHON_LIB
|
||||
|
||||
// Is NSPR installed, and where?
|
||||
#define HAVE_NSPR 1
|
||||
#define NSPR_INCLUDE /usr/local/mozilla/dist/*/include
|
||||
#define NSPR_LIB
|
||||
|
||||
// Is VRPN installed, and where?
|
||||
#define HAVE_VRPN
|
||||
#define VRPN_INCLUDE
|
||||
#define VRPN_LIB
|
||||
|
||||
// Is ZLIB installed, and where?
|
||||
#define HAVE_ZLIB 1
|
||||
#define ZLIB_INCLUDE
|
||||
#define ZLIB_LIB
|
||||
|
||||
// Is OpenGL installed, and where?
|
||||
#define HAVE_GL 1
|
||||
#define GL_INCLUDE
|
||||
#define GL_LIB
|
||||
#define GLU_INCLUDE
|
||||
#define GLU_LIB
|
||||
|
||||
// How about GLX?
|
||||
#define HAVE_GLX 1
|
||||
#define GLX_INCLUDE
|
||||
#define GLX_LIB
|
||||
|
||||
// Glut?
|
||||
#define HAVE_GLUT
|
||||
#define GLUT_INCLUDE
|
||||
#define GLUT_LIB
|
||||
|
||||
// Should we try to build the WGL interface?
|
||||
#define HAVE_WGL
|
||||
|
||||
// Should we try to build the DirectX interface?
|
||||
#define HAVE_DX
|
||||
|
||||
// Do you want to build the Renderman interface?
|
||||
#define HAVE_RIB
|
||||
|
||||
// Is Mikmod installed?
|
||||
#define HAVE_MIKMOD
|
||||
#define MIKMOD_CFLAGS
|
||||
#define MIKMOD_INCLUDE
|
||||
#define MIKMOD_LIB
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// There are also some additional variables that control specific
|
||||
// compiler/platform features or characteristics, defined in the
|
||||
// platform specific file Config.platform.pp. Be sure to inspect
|
||||
// these variables for correctness too. As above, these are
|
||||
// unnecessary when BUILD_TYPE is "autoconf".
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
#include $[TOPDIRPREFIX]Config.$[PLATFORM].pp
|
||||
|
||||
|
||||
// Also pull in whatever package-specific variables there may be.
|
||||
#include $[TOPDIRPREFIX]Package.pp
|
||||
|
||||
|
||||
// If the environment variable PPREMAKE_CONFIG is set, it points to a
|
||||
// user-customized Config.pp file, for instance in the user's home
|
||||
// directory. This file might redefine any of the variables defined
|
||||
// above.
|
||||
#if $[ne $[PPREMAKE_CONFIG],]
|
||||
#include $[PPREMAKE_CONFIG]
|
||||
#endif
|
||||
|
||||
|
||||
// Finally, include the system configure file.
|
||||
#include $[PPREMAKE_DIR]/System.pp
|
||||
211
panda/LocalSetup.pp
Normal file
211
panda/LocalSetup.pp
Normal file
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// LocalSetup.pp
|
||||
//
|
||||
// This file contains further instructions to set up the DTOOL package
|
||||
// when using ppremake. In particular, it creates the dtool_config.h
|
||||
// file based on the user's selected configure variables. This script
|
||||
// need not execute when BUILD_TYPE is "autoconf"; in this case, the
|
||||
// dtool_config.h file will automatically be correctly generated by
|
||||
// configure.
|
||||
//
|
||||
|
||||
#if $[ne $[BUILD_TYPE],autoconf]
|
||||
|
||||
// A couple of variables to output the C #define and #undef
|
||||
// directives, since we can't type them literally.
|
||||
#define define #define
|
||||
#define undef #undef
|
||||
|
||||
#output dtool_config.h
|
||||
#format straight
|
||||
/* dtool_config.h. Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE]. */
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
$[define] STDC_HEADERS 1
|
||||
|
||||
/* Define if your processor stores words with the most significant
|
||||
byte first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#if $[WORDS_BIGENDIAN]
|
||||
$[define] WORDS_BIGENDIAN 1
|
||||
#else
|
||||
$[undef] WORDS_BIGENDIAN
|
||||
#endif
|
||||
|
||||
/* Define if the X Window System is missing or not being used. */
|
||||
$[undef] X_DISPLAY_MISSING
|
||||
|
||||
/* Define if lex declares yytext as a char * by default, not a char[]. */
|
||||
$[undef] YYTEXT_POINTER
|
||||
|
||||
/* Define if the C++ compiler uses namespaces. */
|
||||
#if $[HAVE_NAMESPACE]
|
||||
$[define] HAVE_NAMESPACE 1
|
||||
#else
|
||||
$[undef] HAVE_NAMESPACE
|
||||
#endif
|
||||
|
||||
/* Define if the C++ iostream library supports ios::binary. */
|
||||
#if $[HAVE_IOS_BINARY]
|
||||
$[define] HAVE_IOS_BINARY 1
|
||||
#else
|
||||
$[undef] HAVE_IOS_BINARY
|
||||
#endif
|
||||
|
||||
/* Define if we have Python installed. */
|
||||
#if $[HAVE_PYTHON]
|
||||
$[define] HAVE_PYTHON 1
|
||||
#else
|
||||
$[undef] HAVE_PYTHON
|
||||
#endif
|
||||
|
||||
/* Define if we have NSPR installed. */
|
||||
#if $[HAVE_NSPR]
|
||||
$[define] HAVE_NSPR 1
|
||||
#else
|
||||
$[undef] HAVE_NSPR
|
||||
#endif
|
||||
|
||||
/* Define if we have VRPN installed. */
|
||||
#if $[HAVE_VRPN]
|
||||
$[define] HAVE_VRPN 1
|
||||
#else
|
||||
$[undef] HAVE_VRPN
|
||||
#endif
|
||||
|
||||
/* Define if we have zlib installed. */
|
||||
#if $[HAVE_ZLIB]
|
||||
$[define] HAVE_ZLIB 1
|
||||
#else
|
||||
$[undef] HAVE_ZLIB
|
||||
#endif
|
||||
|
||||
/* Define if we have OpenGL installed and want to build for GL. */
|
||||
#if $[HAVE_GL]
|
||||
$[define] HAVE_GL 1
|
||||
#else
|
||||
$[undef] HAVE_GL
|
||||
#endif
|
||||
|
||||
/* Define if we have GLU installed. */
|
||||
#if $[HAVE_GLU]
|
||||
$[define] HAVE_GLU 1
|
||||
#else
|
||||
$[undef] HAVE_GLU
|
||||
#endif
|
||||
|
||||
/* Define if we have GLX installed and want to build for GLX. */
|
||||
#if $[HAVE_GLX]
|
||||
$[define] HAVE_GLX 1
|
||||
#else
|
||||
$[undef] HAVE_GLX
|
||||
#endif
|
||||
|
||||
/* Define if we have Glut installed and want to build for Glut. */
|
||||
#if $[HAVE_GLUT]
|
||||
$[define] HAVE_GLUT 1
|
||||
#else
|
||||
$[undef] HAVE_GLUT
|
||||
#endif
|
||||
|
||||
/* Define if we want to build the Renderman interface. */
|
||||
#if $[HAVE_RIB]
|
||||
$[define] HAVE_RIB 1
|
||||
#else
|
||||
$[undef] HAVE_RIB
|
||||
#endif
|
||||
|
||||
/* Define if we want to use mikmod for audio. */
|
||||
#if $[HAVE_MIKMOD]
|
||||
$[define] HAVE_MIKMOD 1
|
||||
#else
|
||||
$[undef] HAVE_MIKMOD
|
||||
#endif
|
||||
|
||||
/* Define if we have a gettimeofday() function. */
|
||||
#if $[HAVE_GETTIMEOFDAY]
|
||||
$[define] HAVE_GETTIMEOFDAY 1
|
||||
#else
|
||||
$[undef] HAVE_GETTIMEOFDAY
|
||||
#endif
|
||||
|
||||
/* Define if gettimeofday() takes only one parameter. */
|
||||
#if $[GETTIMEOFDAY_ONE_PARAM]
|
||||
$[define] GETTIMEOFDAY_ONE_PARAM 1
|
||||
#else
|
||||
$[undef] GETTIMEOFDAY_ONE_PARAM
|
||||
#endif
|
||||
|
||||
/* Define if you have the getopt function. */
|
||||
#if $[HAVE_GETOPT]
|
||||
$[define] HAVE_GETOPT 1
|
||||
#else
|
||||
$[undef] HAVE_GETOPT
|
||||
#endif
|
||||
|
||||
/* Define if you have the getopt_long_only function. */
|
||||
#if $[HAVE_GETOPT_LONG_ONLY]
|
||||
$[define] HAVE_GETOPT_LONG_ONLY 1
|
||||
#else
|
||||
$[undef] HAVE_GETOPT_LONG_ONLY
|
||||
#endif
|
||||
|
||||
/* Define if you have the <alloca.h> header file. */
|
||||
$[define] HAVE_ALLOCA_H 1
|
||||
|
||||
/* Define if you have the <io.h> header file. */
|
||||
$[undef] HAVE_IO_H
|
||||
|
||||
/* Define if you have the <iostream> header file. */
|
||||
#if $[HAVE_IOSTREAM]
|
||||
$[define] HAVE_IOSTREAM 1
|
||||
#else
|
||||
$[undef] HAVE_IOSTREAM
|
||||
#endif
|
||||
|
||||
/* Define if you have the <malloc.h> header file. */
|
||||
#if $[HAVE_MALLOC_H]
|
||||
$[define] HAVE_MALLOC_H 1
|
||||
#else
|
||||
$[undef] HAVE_MALLOC_H
|
||||
#endif
|
||||
|
||||
/* Define if you have the <alloca.h> header file. */
|
||||
#if $[HAVE_ALLOCA_H]
|
||||
$[define] HAVE_ALLOCA_H 1
|
||||
#else
|
||||
$[undef] HAVE_ALLOCA_H
|
||||
#endif
|
||||
|
||||
/* Define if you have the <minmax.h> header file. */
|
||||
$[undef] HAVE_MINMAX_H
|
||||
|
||||
/* Define if you have the <sstream> header file. */
|
||||
#if $[HAVE_SSTREAM]
|
||||
$[define] HAVE_SSTREAM 1
|
||||
#else
|
||||
$[undef] HAVE_SSTREAM
|
||||
#endif
|
||||
|
||||
/* Define if you have the <sys/types.h> header file. */
|
||||
#if $[HAVE_SYS_TYPES]
|
||||
$[define] HAVE_SYS_TYPES 1
|
||||
#else
|
||||
$[undef] HAVE_SYS_TYPES
|
||||
#endif
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#if $[HAVE_UNISTD_H]
|
||||
$[define] HAVE_UNISTD_H 1
|
||||
#else
|
||||
$[undef] HAVE_UNISTD_H
|
||||
#endif
|
||||
|
||||
/* Name of package */
|
||||
$[define] PACKAGE $[PACKAGE]
|
||||
|
||||
/* Version number of package */
|
||||
$[define] VERSION $[VERSION]
|
||||
|
||||
#end dtool_config.h
|
||||
|
||||
#endif // BUILD_TYPE
|
||||
11
panda/Package.pp
Normal file
11
panda/Package.pp
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Package.pp
|
||||
//
|
||||
// This file defines a few more configuration variables that are
|
||||
// inconvenient to store in Config.pp, simply because they are more
|
||||
// specific to a particular package and not likely to be edited by a
|
||||
// configuring user.
|
||||
|
||||
// What is the name and version of this source tree?
|
||||
#define PACKAGE panda
|
||||
#define VERSION 0.80
|
||||
10
panda/Sources.pp
Normal file
10
panda/Sources.pp
Normal file
@@ -0,0 +1,10 @@
|
||||
// This is the toplevel directory. It contains configure.in and other
|
||||
// stuff.
|
||||
|
||||
#define DIR_TYPE toplevel
|
||||
|
||||
#define SAMPLE_SOURCE_FILE src/pandabase/pandabase.cxx
|
||||
#define REQUIRED_TREES dtool
|
||||
|
||||
#define EXTRA_DIST \
|
||||
Config.Irix.pp Config.Linux.pp Config.Win32.pp LocalSetup.pp Package.pp
|
||||
933
panda/acinclude.m4
Normal file
933
panda/acinclude.m4
Normal file
@@ -0,0 +1,933 @@
|
||||
AC_DEFUN(AC_GETTIMEOFDAY,
|
||||
[AC_CACHE_CHECK([for gettimeofday()],
|
||||
ac_cv_gettimeofday,
|
||||
[
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/time.h>
|
||||
],[
|
||||
gettimeofday((struct timeval *)NULL, (struct timezone *)NULL);
|
||||
], ac_cv_gettimeofday="2 params", ac_cv_gettimeofday=no)
|
||||
if test "$ac_cv_gettimeofday" = no; then
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/time.h>
|
||||
],[
|
||||
gettimeofday((struct timeval *)NULL, (struct timezone *)NULL);
|
||||
], ac_cv_gettimeofday="1 param", ac_cv_gettimeofday=no)
|
||||
fi
|
||||
])
|
||||
if test "$ac_cv_gettimeofday" = "1 param"; then
|
||||
AC_DEFINE(GETTIMEOFDAY_ONE_PARAM)
|
||||
AC_DEFINE(HAVE_GETTIMEOFDAY)
|
||||
elif test "$ac_cv_gettimeofday" = "2 params"; then
|
||||
AC_DEFINE(HAVE_GETTIMEOFDAY)
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(AC_HEADER_IOSTREAM,
|
||||
[AC_CHECK_HEADERS(iostream,[have_iostream=yes],[have_iostream=no])])
|
||||
|
||||
AC_DEFUN(AC_IOS_BINARY,
|
||||
[AC_CACHE_CHECK([for ios::binary],
|
||||
ac_cv_ios_binary,
|
||||
[
|
||||
if test $have_iostream = yes; then
|
||||
AC_TRY_COMPILE([
|
||||
#include <iostream>
|
||||
],[
|
||||
int x; x = ios::binary;
|
||||
], ac_cv_ios_binary=yes, ac_cv_ios_binary=no)
|
||||
else
|
||||
AC_TRY_COMPILE([
|
||||
#include <iostream.h>
|
||||
],[
|
||||
int x; x = ios::binary;
|
||||
], ac_cv_ios_binary=yes, ac_cv_ios_binary=no)
|
||||
fi
|
||||
|
||||
])
|
||||
if test $ac_cv_ios_binary = yes; then
|
||||
AC_DEFINE(HAVE_IOS_BINARY)
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(AC_NAMESPACE,
|
||||
[AC_CACHE_CHECK([for compiler namespace support],
|
||||
ac_cv_namespace,
|
||||
[AC_TRY_COMPILE(
|
||||
[namespace std { };
|
||||
using namespace std;],
|
||||
[],
|
||||
ac_cv_namespace=yes, ac_cv_namespace=no)])
|
||||
if test $ac_cv_namespace = yes; then
|
||||
AC_DEFINE(HAVE_NAMESPACE)
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl A handy function to see if a library is in a particular directory.
|
||||
dnl AC_CHECK_LIB_LOC(directory, library, function, action-if-found, action-if-not-found, other-libraries)
|
||||
dnl
|
||||
AC_DEFUN(AC_CHECK_LIB_LOC,
|
||||
[AC_MSG_CHECKING([for lib$2 in $1])
|
||||
ac_lib_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
|
||||
AC_CACHE_VAL(ac_cv_lib_loc_$ac_lib_var,
|
||||
[ac_save_LIBS="$LIBS"
|
||||
LIBS="-L$1 -l$2 $6 $LIBS"
|
||||
AC_TRY_LINK(dnl
|
||||
ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
])dnl
|
||||
[/* We use char because int might match the return type of a gcc2
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char $3();
|
||||
],
|
||||
[$3()],
|
||||
eval "ac_cv_lib_loc_$ac_lib_var=yes",
|
||||
eval "ac_cv_lib_loc_$ac_lib_var=no")
|
||||
LIBS="$ac_save_LIBS"
|
||||
])dnl
|
||||
if eval "test \"`echo '$ac_cv_lib_loc_'$ac_lib_var`\" = yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$4], ,
|
||||
[LIBS="-L$1 -l$2 $LIBS"
|
||||
], [$4])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
ifelse([$5], , , [$5
|
||||
])dnl
|
||||
fi
|
||||
])
|
||||
|
||||
dnl A handy function to search a number of possible locations for a library.
|
||||
dnl AC_SEARCH_LIB(search-dirs, library, function, package, other-libraries)
|
||||
dnl
|
||||
dnl Sets $package_LIB to the directory containing the library, or to the
|
||||
dnl string "no" if the library cannot be found.
|
||||
AC_DEFUN(AC_SEARCH_LIB, [
|
||||
ac_found_lib="no"
|
||||
if test "$1" = ""; then
|
||||
AC_CHECK_LIB($2, $3, [ ac_found_lib=""; ],, $5)
|
||||
else
|
||||
for ac_check_dir in $1; do
|
||||
if test "$ac_found_lib" = "no"; then
|
||||
AC_CHECK_LIB_LOC($ac_check_dir, $2, $3, [ ac_found_lib="$ac_check_dir"; ],, $5)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
$4_LIB="$ac_found_lib"
|
||||
])
|
||||
|
||||
dnl A handy function to see if a header file is in a particular directory.
|
||||
dnl AC_CHECK_HEADER_LOC(directory, header, action-if-found, action-if-not-found)
|
||||
dnl
|
||||
AC_DEFUN(AC_CHECK_HEADER_LOC, [
|
||||
AC_MSG_CHECKING([for $2 in $1])
|
||||
ac_include_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
|
||||
AC_CACHE_VAL(ac_cv_include_loc_$ac_include_var, [
|
||||
ac_save_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="-I$1 $CPPFLAGS"
|
||||
AC_TRY_CPP([#include <$2>], ac_ch_found_it="yes", ac_ch_found_it="no")
|
||||
if test "$ac_ch_found_it" = "yes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$3], , :, [$3])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
ifelse([$4], , , [$4])
|
||||
fi
|
||||
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
dnl A handy function to search a number of possible locations for a header
|
||||
dnl file.
|
||||
dnl
|
||||
dnl AC_SEARCH_HEADER(search-dirs, header, package)
|
||||
dnl
|
||||
dnl Sets $package_INCLUDE to the directory containing the header, or to
|
||||
dnl the string "no" if the header cannot be found.
|
||||
AC_DEFUN(AC_SEARCH_HEADER, [
|
||||
ac_found_header="no"
|
||||
if test "$1" = ""; then
|
||||
AC_CHECK_HEADER($2, [ ac_found_header="";])
|
||||
else
|
||||
for ac_check_dir in $1; do
|
||||
if test "$ac_found_header" = "no"; then
|
||||
AC_CHECK_HEADER_LOC($ac_check_dir, $2, [ ac_found_header="$ac_check_dir";])
|
||||
fi
|
||||
done
|
||||
fi
|
||||
$3_INCLUDE="$ac_found_header"
|
||||
])
|
||||
|
||||
|
||||
dnl A handy function to scan for a third-party package, consisting of at
|
||||
dnl least a library and an include file. A few assumptions are made about
|
||||
dnl the relationships between lib and include directories.
|
||||
dnl
|
||||
dnl AC_SEARCH_PACKAGE(search-dirs, package-names, header, library, function, package, other-libraries)
|
||||
dnl
|
||||
dnl search-dirs is the whitespace-separated list of directory prefixes to
|
||||
dnl check.
|
||||
dnl package-names is a whitespace-separated list of possible names the
|
||||
dnl package may have been installed under.
|
||||
dnl
|
||||
dnl For each combination of ${search-dir} and ${package-name}, the following
|
||||
dnl directories are searched:
|
||||
dnl
|
||||
dnl ${search-dir}
|
||||
dnl ${search-dir}/lib
|
||||
dnl ${search-dir}/${package-name}
|
||||
dnl ${search-dir}/${package-name}/lib
|
||||
dnl ${search-dir}/lib/${package-name}
|
||||
dnl
|
||||
dnl And similarly for include.
|
||||
dnl
|
||||
dnl Sets the variables $package_INCLUDE and $package_LIB to the directories
|
||||
dnl containing the header file and library, respectively. If both pieces
|
||||
dnl are located, also sets the variable $package_PKG to "yes"; otherwise,
|
||||
dnl sets the variable $package_PKG to "no".
|
||||
dnl
|
||||
AC_DEFUN(AC_SEARCH_PACKAGE, [
|
||||
$6_LIB="no"
|
||||
$6_INCLUDE="no"
|
||||
$6_PKG="no"
|
||||
|
||||
dnl Look for the library.
|
||||
AC_SEARCH_LIB("", $4, $5, $6, $7)
|
||||
for ac_sp_dir in $1; do
|
||||
if test "[$]$6_LIB" = "no"; then
|
||||
AC_SEARCH_LIB("$ac_sp_dir" "$ac_sp_dir/lib", $4, $5, $6, $7)
|
||||
for ac_sp_pkg in $2; do
|
||||
if test "[$]$6_LIB" = "no"; then
|
||||
AC_SEARCH_LIB("$ac_sp_dir/$ac_sp_pkg" "$ac_sp_dir/$ac_sp_pkg/lib" \
|
||||
"$ac_sp_dir/lib/$ac_sp_pkg", $4, $5, $6, $7)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
dnl Now look for the header file. Don't bother looking if the library
|
||||
dnl wasn't found.
|
||||
if test "[$]$6_LIB" != "no"; then
|
||||
dnl First look in the obvious directory corresponding to the lib dir.
|
||||
ac_sp_testinc=`echo [$]$6_LIB | sed 's:/lib:/include:'`
|
||||
AC_SEARCH_HEADER("$ac_sp_testinc", $3, $6)
|
||||
|
||||
dnl If it wasn't found there, cast about.
|
||||
if test "[$]$6_INCLUDE" = "no"; then
|
||||
for ac_sp_dir in $1; do
|
||||
if test "[$]$6_INCLUDE" = "no"; then
|
||||
AC_SEARCH_HEADER("$ac_sp_dir" "$ac_sp_dir/include", $3, $6)
|
||||
for ac_sp_pkg in $2; do
|
||||
if test "[$]$6_INCLUDE" = "no"; then
|
||||
AC_SEARCH_HEADER("$ac_sp_dir/$ac_sp_pkg" \
|
||||
"$ac_sp_dir/$ac_sp_pkg/include" \
|
||||
"$ac_sp_dir/include/$ac_sp_pkg", $3, $6)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
dnl If we got both a header and a library, set the PKG variable.
|
||||
if test "[$]$6_INCLUDE" != "no"; then
|
||||
$6_PKG="yes"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
dnl A handy function, similar to AC_SEARCH_PACKAGE, above, that looks for a
|
||||
dnl package that only consists of header files, no libraries.
|
||||
dnl
|
||||
dnl AC_SEARCH_HPACKAGE(search-dirs, package-names, header, package)
|
||||
dnl
|
||||
dnl search-dirs is the whitespace-separated list of directory prefixes to
|
||||
dnl check.
|
||||
dnl package-names is a whitespace-separated list of possible names the
|
||||
dnl package may have been installed under.
|
||||
dnl
|
||||
dnl For each combination of ${search-dir} and ${package-name}, the following
|
||||
dnl directories are searched:
|
||||
dnl
|
||||
dnl ${search-dir}
|
||||
dnl ${search-dir}/include
|
||||
dnl ${search-dir}/${package-name}
|
||||
dnl ${search-dir}/${package-name}/include
|
||||
dnl ${search-dir}/include/${package-name}
|
||||
dnl
|
||||
dnl Sets the variable $package_INCLUDE to the directory containing the
|
||||
dnl header file, and sets the variable $package_PKG to "yes"; if the
|
||||
dnl directory is not found, sets the variable $package_PKG to "no".
|
||||
dnl
|
||||
AC_DEFUN(AC_SEARCH_HPACKAGE, [
|
||||
$4_INCLUDE="no"
|
||||
$4_PKG="no"
|
||||
|
||||
dnl Look for the header.
|
||||
AC_SEARCH_HEADER("", $3, $4)
|
||||
for ac_sp_dir in $1; do
|
||||
if test "[$]$4_INCLUDE" = "no"; then
|
||||
AC_SEARCH_HEADER("$ac_sp_dir" "$ac_sp_dir/include", $3, $4)
|
||||
for ac_sp_pkg in $2; do
|
||||
if test "[$]$4_INCLUDE" = "no"; then
|
||||
AC_SEARCH_HEADER("$ac_sp_dir/$ac_sp_pkg" \
|
||||
"$ac_sp_dir/$ac_sp_pkg/include" \
|
||||
"$ac_sp_dir/include/$ac_sp_pkg", $3, $4)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
dnl If we got both a header file, set the PKG variable.
|
||||
if test "[$]$4_INCLUDE" != "no"; then
|
||||
$4_PKG="yes"
|
||||
fi
|
||||
])
|
||||
|
||||
# Define a conditional.
|
||||
|
||||
AC_DEFUN(AM_CONDITIONAL,
|
||||
[AC_SUBST($1_TRUE)
|
||||
AC_SUBST($1_FALSE)
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi])
|
||||
|
||||
|
||||
|
||||
|
||||
# Configure paths for GTK--
|
||||
# Erik Andersen 30 May 1998
|
||||
# Modified by Tero Pulkkinen (added the compiler checks... I hope they work..)
|
||||
|
||||
dnl Test for GTKMM, and define GTKMM_CFLAGS and GTKMM_LIBS
|
||||
dnl to be used as follows:
|
||||
dnl AM_PATH_GTKMM([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
|
||||
dnl
|
||||
AC_DEFUN(AM_PATH_GTKMM,
|
||||
[dnl
|
||||
dnl Get the cflags and libraries from the gtkmm-config script
|
||||
dnl
|
||||
AC_ARG_WITH(gtkmm-prefix,[ --with-gtkmm-prefix=PREFIX
|
||||
Prefix where GTK-- is installed (optional)],
|
||||
gtkmm_config_prefix="$withval", gtkmm_config_prefix="")
|
||||
AC_ARG_WITH(gtkmm-exec-prefix,[ --with-gtkmm-exec-prefix=PREFIX
|
||||
Exec prefix where GTK-- is installed (optional)],
|
||||
gtkmm_config_exec_prefix="$withval", gtkmm_config_exec_prefix="")
|
||||
AC_ARG_ENABLE(gtkmmtest, [ --disable-gtkmmtest Do not try to compile and run a test GTK-- program],
|
||||
, enable_gtkmmtest=yes)
|
||||
|
||||
if test x$gtkmm_config_exec_prefix != x ; then
|
||||
gtkmm_config_args="$gtkmm_config_args --exec-prefix=$gtkmm_config_exec_prefix"
|
||||
if test x${GTKMM_CONFIG+set} != xset ; then
|
||||
GTKMM_CONFIG=$gtkmm_config_exec_prefix/bin/gtkmm-config
|
||||
fi
|
||||
fi
|
||||
if test x$gtkmm_config_prefix != x ; then
|
||||
gtkmm_config_args="$gtkmm_config_args --prefix=$gtkmm_config_prefix"
|
||||
if test x${GTKMM_CONFIG+set} != xset ; then
|
||||
GTKMM_CONFIG=$gtkmm_config_prefix/bin/gtkmm-config
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_PATH_PROG(GTKMM_CONFIG, gtkmm-config, no)
|
||||
min_gtkmm_version=ifelse([$1], ,0.10.0,$1)
|
||||
|
||||
AC_MSG_CHECKING(for GTK-- - version >= $min_gtkmm_version)
|
||||
no_gtkmm=""
|
||||
if test "$GTKMM_CONFIG" = "no" ; then
|
||||
no_gtkmm=yes
|
||||
else
|
||||
AC_LANG_SAVE
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
GTKMM_CFLAGS=`$GTKMM_CONFIG $gtkmm_config_args --cflags`
|
||||
GTKMM_LIBS=`$GTKMM_CONFIG $gtkmm_config_args --libs`
|
||||
gtkmm_config_major_version=`$GTKMM_CONFIG $gtkmm_config_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
|
||||
gtkmm_config_minor_version=`$GTKMM_CONFIG $gtkmm_config_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
|
||||
gtkmm_config_micro_version=`$GTKMM_CONFIG $gtkmm_config_args --version | \
|
||||
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
|
||||
if test "x$enable_gtkmmtest" = "xyes" ; then
|
||||
ac_save_CXXFLAGS="$CXXFLAGS"
|
||||
ac_save_LIBS="$LIBS"
|
||||
CXXFLAGS="$CXXFLAGS $GTKMM_CFLAGS"
|
||||
LIBS="$LIBS $GTKMM_LIBS"
|
||||
dnl
|
||||
dnl Now check if the installed GTK-- is sufficiently new. (Also sanity
|
||||
dnl checks the results of gtkmm-config to some extent
|
||||
dnl
|
||||
rm -f conf.gtkmmtest
|
||||
AC_TRY_RUN([
|
||||
#include <gtk--.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int major, minor, micro;
|
||||
char *tmp_version;
|
||||
|
||||
system ("touch conf.gtkmmtest");
|
||||
|
||||
/* HP/UX 0 (%@#!) writes to sscanf strings */
|
||||
tmp_version = g_strdup("$min_gtkmm_version");
|
||||
if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) {
|
||||
printf("%s, bad version string\n", "$min_gtkmm_version");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((gtkmm_major_version != $gtkmm_config_major_version) ||
|
||||
(gtkmm_minor_version != $gtkmm_config_minor_version) ||
|
||||
(gtkmm_micro_version != $gtkmm_config_micro_version))
|
||||
{
|
||||
printf("\n*** 'gtkmm-config --version' returned %d.%d.%d, but GTK-- (%d.%d.%d)\n",
|
||||
$gtkmm_config_major_version, $gtkmm_config_minor_version, $gtkmm_config_micro_version,
|
||||
gtkmm_major_version, gtkmm_minor_version, gtkmm_micro_version);
|
||||
printf ("*** was found! If gtkmm-config was correct, then it is best\n");
|
||||
printf ("*** to remove the old version of GTK--. You may also be able to fix the error\n");
|
||||
printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
|
||||
printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
|
||||
printf("*** required on your system.\n");
|
||||
printf("*** If gtkmm-config was wrong, set the environment variable GTKMM_CONFIG\n");
|
||||
printf("*** to point to the correct copy of gtkmm-config, and remove the file config.cache\n");
|
||||
printf("*** before re-running configure\n");
|
||||
}
|
||||
/* GTK-- does not have the GTKMM_*_VERSION constants */
|
||||
/*
|
||||
else if ((gtkmm_major_version != GTKMM_MAJOR_VERSION) ||
|
||||
(gtkmm_minor_version != GTKMM_MINOR_VERSION) ||
|
||||
(gtkmm_micro_version != GTKMM_MICRO_VERSION))
|
||||
{
|
||||
printf("*** GTK-- header files (version %d.%d.%d) do not match\n",
|
||||
GTKMM_MAJOR_VERSION, GTKMM_MINOR_VERSION, GTKMM_MICRO_VERSION);
|
||||
printf("*** library (version %d.%d.%d)\n",
|
||||
gtkmm_major_version, gtkmm_minor_version, gtkmm_micro_version);
|
||||
}
|
||||
*/
|
||||
else
|
||||
{
|
||||
if ((gtkmm_major_version > major) ||
|
||||
((gtkmm_major_version == major) && (gtkmm_minor_version > minor)) ||
|
||||
((gtkmm_major_version == major) && (gtkmm_minor_version == minor) && (gtkmm_micro_version >= micro)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n*** An old version of GTK-- (%d.%d.%d) was found.\n",
|
||||
gtkmm_major_version, gtkmm_minor_version, gtkmm_micro_version);
|
||||
printf("*** You need a version of GTK-- newer than %d.%d.%d. The latest version of\n",
|
||||
major, minor, micro);
|
||||
printf("*** GTK-- is always available from ftp://ftp.gtk.org.\n");
|
||||
printf("***\n");
|
||||
printf("*** If you have already installed a sufficiently new version, this error\n");
|
||||
printf("*** probably means that the wrong copy of the gtkmm-config shell script is\n");
|
||||
printf("*** being found. The easiest way to fix this is to remove the old version\n");
|
||||
printf("*** of GTK--, but you can also set the GTKMM_CONFIG environment to point to the\n");
|
||||
printf("*** correct copy of gtkmm-config. (In this case, you will have to\n");
|
||||
printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
|
||||
printf("*** so that the correct libraries are found at run-time))\n");
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
],, no_gtkmm=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
|
||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
fi
|
||||
if test "x$no_gtkmm" = x ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
if test "$GTKMM_CONFIG" = "no" ; then
|
||||
echo "*** The gtkmm-config script installed by GTK-- could not be found"
|
||||
echo "*** If GTK-- was installed in PREFIX, make sure PREFIX/bin is in"
|
||||
echo "*** your path, or set the GTKMM_CONFIG environment variable to the"
|
||||
echo "*** full path to gtkmm-config."
|
||||
echo "*** The gtkmm-config script was not available in GTK-- versions"
|
||||
echo "*** prior to 0.9.12. Perhaps you need to update your installed"
|
||||
echo "*** version to 0.9.12 or later"
|
||||
else
|
||||
if test -f conf.gtkmmtest ; then
|
||||
:
|
||||
else
|
||||
echo "*** Could not run GTK-- test program, checking why..."
|
||||
CXXFLAGS="$CFLAGS $GTKMM_CXXFLAGS"
|
||||
LIBS="$LIBS $GTKMM_LIBS"
|
||||
AC_TRY_LINK([
|
||||
#include <gtk--.h>
|
||||
#include <stdio.h>
|
||||
], [ return ((gtkmm_major_version) || (gtkmm_minor_version) || (gtkmm_micro_version)); ],
|
||||
[ echo "*** The test program compiled, but did not run. This usually means"
|
||||
echo "*** that the run-time linker is not finding GTK-- or finding the wrong"
|
||||
echo "*** version of GTK--. If it is not finding GTK--, you'll need to set your"
|
||||
echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
|
||||
echo "*** to the installed location Also, make sure you have run ldconfig if that"
|
||||
echo "*** is required on your system"
|
||||
echo "***"
|
||||
echo "*** If you have an old version installed, it is best to remove it, although"
|
||||
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
|
||||
[ echo "*** The test program failed to compile or link. See the file config.log for the"
|
||||
echo "*** exact error that occured. This usually means GTK-- was incorrectly installed"
|
||||
echo "*** or that you have moved GTK-- since it was installed. In the latter case, you"
|
||||
echo "*** may want to edit the gtkmm-config script: $GTKMM_CONFIG" ])
|
||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
||||
LIBS="$ac_save_LIBS"
|
||||
fi
|
||||
fi
|
||||
GTKMM_CFLAGS=""
|
||||
GTKMM_LIBS=""
|
||||
ifelse([$3], , :, [$3])
|
||||
AC_LANG_RESTORE
|
||||
fi
|
||||
AC_SUBST(GTKMM_CFLAGS)
|
||||
AC_SUBST(GTKMM_LIBS)
|
||||
rm -f conf.gtkmmtest
|
||||
])
|
||||
|
||||
|
||||
## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*-
|
||||
## Copyright (C) 1996-1999 Free Software Foundation, Inc.
|
||||
## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 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 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.
|
||||
##
|
||||
## 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.
|
||||
|
||||
# serial 40 AC_PROG_LIBTOOL
|
||||
AC_DEFUN(AC_PROG_LIBTOOL,
|
||||
[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
|
||||
|
||||
# Save cache, so that ltconfig can load it
|
||||
AC_CACHE_SAVE
|
||||
|
||||
# Actually configure libtool. ac_aux_dir is where install-sh is found.
|
||||
CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
|
||||
LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
|
||||
LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
|
||||
DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
|
||||
${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
|
||||
$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
|
||||
|| AC_MSG_ERROR([libtool configure failed])
|
||||
|
||||
# Reload cache, that may have been modified by ltconfig
|
||||
AC_CACHE_LOAD
|
||||
|
||||
# This can be used to rebuild libtool when needed
|
||||
LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
|
||||
|
||||
# Always use our own libtool.
|
||||
LIBTOOL='$(SHELL) $(top_builddir)/libtool'
|
||||
AC_SUBST(LIBTOOL)dnl
|
||||
|
||||
# Redirect the config.log output again, so that the ltconfig log is not
|
||||
# clobbered by the next message.
|
||||
exec 5>>./config.log
|
||||
])
|
||||
|
||||
AC_DEFUN(AC_LIBTOOL_SETUP,
|
||||
[AC_PREREQ(2.13)dnl
|
||||
AC_REQUIRE([AC_ENABLE_SHARED])dnl
|
||||
AC_REQUIRE([AC_ENABLE_STATIC])dnl
|
||||
AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
|
||||
AC_REQUIRE([AC_PROG_RANLIB])dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_PROG_LD])dnl
|
||||
AC_REQUIRE([AC_PROG_NM])dnl
|
||||
AC_REQUIRE([AC_PROG_LN_S])dnl
|
||||
dnl
|
||||
|
||||
# Check for any special flags to pass to ltconfig.
|
||||
#
|
||||
# the following will cause an existing older ltconfig to fail, so
|
||||
# we ignore this at the expense of the cache file... Checking this
|
||||
# will just take longer ... bummer!
|
||||
#libtool_flags="--cache-file=$cache_file"
|
||||
#
|
||||
test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
|
||||
test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
|
||||
test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
|
||||
test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
|
||||
test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
|
||||
ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN],
|
||||
[libtool_flags="$libtool_flags --enable-dlopen"])
|
||||
ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
|
||||
[libtool_flags="$libtool_flags --enable-win32-dll"])
|
||||
AC_ARG_ENABLE(libtool-lock,
|
||||
[ --disable-libtool-lock avoid locking (might break parallel builds)])
|
||||
test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
|
||||
test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
|
||||
|
||||
# Some flags need to be propagated to the compiler or linker for good
|
||||
# libtool support.
|
||||
case "$host" in
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '[#]line __oline__ "configure"' > conftest.$ac_ext
|
||||
if AC_TRY_EVAL(ac_compile); then
|
||||
case "`/usr/bin/file conftest.o`" in
|
||||
*32-bit*)
|
||||
LD="${LD-ld} -32"
|
||||
;;
|
||||
*N32*)
|
||||
LD="${LD-ld} -n32"
|
||||
;;
|
||||
*64-bit*)
|
||||
LD="${LD-ld} -64"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
rm -rf conftest*
|
||||
;;
|
||||
|
||||
*-*-sco3.2v5*)
|
||||
# On SCO OpenServer 5, we need -belf to get full-featured binaries.
|
||||
SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -belf"
|
||||
AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
|
||||
[AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
|
||||
if test x"$lt_cv_cc_needs_belf" != x"yes"; then
|
||||
# this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
|
||||
CFLAGS="$SAVE_CFLAGS"
|
||||
fi
|
||||
;;
|
||||
|
||||
ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
|
||||
[*-*-cygwin* | *-*-mingw*)
|
||||
AC_CHECK_TOOL(DLLTOOL, dlltool, false)
|
||||
AC_CHECK_TOOL(AS, as, false)
|
||||
AC_CHECK_TOOL(OBJDUMP, objdump, false)
|
||||
;;
|
||||
])
|
||||
esac
|
||||
])
|
||||
|
||||
# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
|
||||
AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
|
||||
|
||||
# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
|
||||
AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
|
||||
|
||||
# AC_ENABLE_SHARED - implement the --enable-shared flag
|
||||
# Usage: AC_ENABLE_SHARED[(DEFAULT)]
|
||||
# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
|
||||
# `yes'.
|
||||
AC_DEFUN(AC_ENABLE_SHARED, [dnl
|
||||
define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
|
||||
AC_ARG_ENABLE(shared,
|
||||
changequote(<<, >>)dnl
|
||||
<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
|
||||
changequote([, ])dnl
|
||||
[p=${PACKAGE-default}
|
||||
case "$enableval" in
|
||||
yes) enable_shared=yes ;;
|
||||
no) enable_shared=no ;;
|
||||
*)
|
||||
enable_shared=no
|
||||
# Look at the argument we got. We use all the common list separators.
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
|
||||
for pkg in $enableval; do
|
||||
if test "X$pkg" = "X$p"; then
|
||||
enable_shared=yes
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
;;
|
||||
esac],
|
||||
enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
|
||||
])
|
||||
|
||||
# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
|
||||
AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
AC_ENABLE_SHARED(no)])
|
||||
|
||||
# AC_ENABLE_STATIC - implement the --enable-static flag
|
||||
# Usage: AC_ENABLE_STATIC[(DEFAULT)]
|
||||
# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
|
||||
# `yes'.
|
||||
AC_DEFUN(AC_ENABLE_STATIC, [dnl
|
||||
define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
|
||||
AC_ARG_ENABLE(static,
|
||||
changequote(<<, >>)dnl
|
||||
<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
|
||||
changequote([, ])dnl
|
||||
[p=${PACKAGE-default}
|
||||
case "$enableval" in
|
||||
yes) enable_static=yes ;;
|
||||
no) enable_static=no ;;
|
||||
*)
|
||||
enable_static=no
|
||||
# Look at the argument we got. We use all the common list separators.
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
|
||||
for pkg in $enableval; do
|
||||
if test "X$pkg" = "X$p"; then
|
||||
enable_static=yes
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
;;
|
||||
esac],
|
||||
enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
|
||||
])
|
||||
|
||||
# AC_DISABLE_STATIC - set the default static flag to --disable-static
|
||||
AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
AC_ENABLE_STATIC(no)])
|
||||
|
||||
|
||||
# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
|
||||
# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
|
||||
# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
|
||||
# `yes'.
|
||||
AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl
|
||||
define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
|
||||
AC_ARG_ENABLE(fast-install,
|
||||
changequote(<<, >>)dnl
|
||||
<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
|
||||
changequote([, ])dnl
|
||||
[p=${PACKAGE-default}
|
||||
case "$enableval" in
|
||||
yes) enable_fast_install=yes ;;
|
||||
no) enable_fast_install=no ;;
|
||||
*)
|
||||
enable_fast_install=no
|
||||
# Look at the argument we got. We use all the common list separators.
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
|
||||
for pkg in $enableval; do
|
||||
if test "X$pkg" = "X$p"; then
|
||||
enable_fast_install=yes
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
;;
|
||||
esac],
|
||||
enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
|
||||
])
|
||||
|
||||
# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
|
||||
AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
AC_ENABLE_FAST_INSTALL(no)])
|
||||
|
||||
# AC_PROG_LD - find the path to the GNU or non-GNU linker
|
||||
AC_DEFUN(AC_PROG_LD,
|
||||
[AC_ARG_WITH(gnu-ld,
|
||||
[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
|
||||
test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
|
||||
ac_prog=ld
|
||||
if test "$ac_cv_prog_gcc" = yes; then
|
||||
# Check if gcc -print-prog-name=ld gives a path.
|
||||
AC_MSG_CHECKING([for ld used by GCC])
|
||||
ac_prog=`($CC -print-prog-name=ld) 2>&5`
|
||||
case "$ac_prog" in
|
||||
# Accept absolute paths.
|
||||
changequote(,)dnl
|
||||
[\\/]* | [A-Za-z]:[\\/]*)
|
||||
re_direlt='/[^/][^/]*/\.\./'
|
||||
changequote([,])dnl
|
||||
# Canonicalize the path of ld
|
||||
ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
|
||||
while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
|
||||
ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
|
||||
done
|
||||
test -z "$LD" && LD="$ac_prog"
|
||||
;;
|
||||
"")
|
||||
# If it fails, then pretend we aren't using GCC.
|
||||
ac_prog=ld
|
||||
;;
|
||||
*)
|
||||
# If it is relative, then search for the first ld in PATH.
|
||||
with_gnu_ld=unknown
|
||||
;;
|
||||
esac
|
||||
elif test "$with_gnu_ld" = yes; then
|
||||
AC_MSG_CHECKING([for GNU ld])
|
||||
else
|
||||
AC_MSG_CHECKING([for non-GNU ld])
|
||||
fi
|
||||
AC_CACHE_VAL(ac_cv_path_LD,
|
||||
[if test -z "$LD"; then
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
|
||||
for ac_dir in $PATH; do
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
|
||||
ac_cv_path_LD="$ac_dir/$ac_prog"
|
||||
# Check to see if the program is GNU ld. I'd rather use --version,
|
||||
# but apparently some GNU ld's only accept -v.
|
||||
# Break only if it was the GNU/non-GNU ld that we prefer.
|
||||
if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
|
||||
test "$with_gnu_ld" != no && break
|
||||
else
|
||||
test "$with_gnu_ld" != yes && break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
else
|
||||
ac_cv_path_LD="$LD" # Let the user override the test with a path.
|
||||
fi])
|
||||
LD="$ac_cv_path_LD"
|
||||
if test -n "$LD"; then
|
||||
AC_MSG_RESULT($LD)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
|
||||
AC_SUBST(LD)
|
||||
AC_PROG_LD_GNU
|
||||
])
|
||||
|
||||
AC_DEFUN(AC_PROG_LD_GNU,
|
||||
[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
|
||||
[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
|
||||
if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
|
||||
ac_cv_prog_gnu_ld=yes
|
||||
else
|
||||
ac_cv_prog_gnu_ld=no
|
||||
fi])
|
||||
])
|
||||
|
||||
# AC_PROG_NM - find the path to a BSD-compatible name lister
|
||||
AC_DEFUN(AC_PROG_NM,
|
||||
[AC_MSG_CHECKING([for BSD-compatible nm])
|
||||
AC_CACHE_VAL(ac_cv_path_NM,
|
||||
[if test -n "$NM"; then
|
||||
# Let the user override the test.
|
||||
ac_cv_path_NM="$NM"
|
||||
else
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
|
||||
for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
|
||||
# Check to see if the nm accepts a BSD-compat flag.
|
||||
# Adding the `sed 1q' prevents false positives on HP-UX, which says:
|
||||
# nm: unknown option "B" ignored
|
||||
if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
|
||||
ac_cv_path_NM="$ac_dir/nm -B"
|
||||
break
|
||||
elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
|
||||
ac_cv_path_NM="$ac_dir/nm -p"
|
||||
break
|
||||
else
|
||||
ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
|
||||
continue # so that we can try to find one that supports BSD flags
|
||||
fi
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
|
||||
fi])
|
||||
NM="$ac_cv_path_NM"
|
||||
AC_MSG_RESULT([$NM])
|
||||
AC_SUBST(NM)
|
||||
])
|
||||
|
||||
# AC_CHECK_LIBM - check for math library
|
||||
AC_DEFUN(AC_CHECK_LIBM,
|
||||
[AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
LIBM=
|
||||
case "$host" in
|
||||
*-*-beos* | *-*-cygwin*)
|
||||
# These system don't have libm
|
||||
;;
|
||||
*-ncr-sysv4.3*)
|
||||
AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
|
||||
AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
|
||||
;;
|
||||
*)
|
||||
AC_CHECK_LIB(m, main, LIBM="-lm")
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
|
||||
# the libltdl convenience library, adds --enable-ltdl-convenience to
|
||||
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
|
||||
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
|
||||
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
|
||||
# '${top_builddir}/' (note the single quotes!) if your package is not
|
||||
# flat, and, if you're not using automake, define top_builddir as
|
||||
# appropriate in the Makefiles.
|
||||
AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
case "$enable_ltdl_convenience" in
|
||||
no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
|
||||
"") enable_ltdl_convenience=yes
|
||||
ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
|
||||
esac
|
||||
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
|
||||
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
|
||||
])
|
||||
|
||||
# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
|
||||
# the libltdl installable library, and adds --enable-ltdl-install to
|
||||
# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
|
||||
# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
|
||||
# to be `${top_builddir}/libltdl'. Make sure you start DIR with
|
||||
# '${top_builddir}/' (note the single quotes!) if your package is not
|
||||
# flat, and, if you're not using automake, define top_builddir as
|
||||
# appropriate in the Makefiles.
|
||||
# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
|
||||
AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
|
||||
AC_CHECK_LIB(ltdl, main,
|
||||
[test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
|
||||
[if test x"$enable_ltdl_install" = xno; then
|
||||
AC_MSG_WARN([libltdl not installed, but installation disabled])
|
||||
else
|
||||
enable_ltdl_install=yes
|
||||
fi
|
||||
])
|
||||
if test x"$enable_ltdl_install" = x"yes"; then
|
||||
ac_configure_args="$ac_configure_args --enable-ltdl-install"
|
||||
LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
|
||||
INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
|
||||
else
|
||||
ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
|
||||
LIBLTDL="-lltdl"
|
||||
INCLTDL=
|
||||
fi
|
||||
])
|
||||
|
||||
dnl old names
|
||||
AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
|
||||
AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
|
||||
AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
|
||||
AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
|
||||
AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
|
||||
AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
|
||||
AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
|
||||
|
||||
dnl This is just to silence aclocal about the macro not being used
|
||||
ifelse([AC_DISABLE_FAST_INSTALL])dnl
|
||||
7
panda/metalibs/Sources.pp
Normal file
7
panda/metalibs/Sources.pp
Normal file
@@ -0,0 +1,7 @@
|
||||
// This is a group directory: a directory level above a number of
|
||||
// source subdirectories.
|
||||
|
||||
#define DIR_TYPE group
|
||||
|
||||
// The metalibs directory always depends on the src directory.
|
||||
#define DEPENDS src
|
||||
25
panda/metalibs/panda/Sources.pp
Normal file
25
panda/metalibs/panda/Sources.pp
Normal file
@@ -0,0 +1,25 @@
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDA
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
pstatclient grutil chan chancfg \
|
||||
char chat collide cull device \
|
||||
dgraph display gobj graph gsgbase \
|
||||
gsgmisc light linmath mathutil net pnm \
|
||||
pnmimagetypes pnmimage sgattrib sgmanip sgraph sgraphutil \
|
||||
switchnode text tform lerp loader putil effects \
|
||||
audio pandabase
|
||||
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET panda
|
||||
|
||||
#define SOURCES panda.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/panda/panda.cxx
Normal file
9
panda/metalibs/panda/panda.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: panda.cxx
|
||||
// Created by: drose (15May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpanda.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpanda.
|
||||
21
panda/metalibs/pandadx/Sources.pp
Normal file
21
panda/metalibs/pandadx/Sources.pp
Normal file
@@ -0,0 +1,21 @@
|
||||
#define DIRECTORY_IF_DX yes
|
||||
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDADX
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
dxgsg wdxdisplay
|
||||
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET pandadx
|
||||
|
||||
#define SOURCES pandadx.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/pandadx/pandadx.cxx
Normal file
9
panda/metalibs/pandadx/pandadx.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: pandadx.cxx
|
||||
// Created by: drose (15May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpandadx.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpandadx.
|
||||
19
panda/metalibs/pandaegg/Sources.pp
Normal file
19
panda/metalibs/pandaegg/Sources.pp
Normal file
@@ -0,0 +1,19 @@
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDAEGG
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
egg2sg egg builder
|
||||
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET pandaegg
|
||||
|
||||
#define SOURCES pandaegg.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/pandaegg/pandaegg.cxx
Normal file
9
panda/metalibs/pandaegg/pandaegg.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: pandaegg.cxx
|
||||
// Created by: drose (16May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpandaegg.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpandaegg.
|
||||
17
panda/metalibs/pandaexpress/Sources.pp
Normal file
17
panda/metalibs/pandaexpress/Sources.pp
Normal file
@@ -0,0 +1,17 @@
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDAEXPRESS
|
||||
|
||||
#define LOCAL_LIBS downloader event ipc express pandabase
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET pandaexpress
|
||||
|
||||
#define SOURCES pandaexpress.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/pandaexpress/pandaexpress.cxx
Normal file
9
panda/metalibs/pandaexpress/pandaexpress.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: pandaexpress.cxx
|
||||
// Created by: drose (15May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpanda.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpanda.
|
||||
21
panda/metalibs/pandagl/Sources.pp
Normal file
21
panda/metalibs/pandagl/Sources.pp
Normal file
@@ -0,0 +1,21 @@
|
||||
#define DIRECTORY_IF_GL yes
|
||||
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDAGL
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
glgsg glxdisplay // sgiglxdisplay
|
||||
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET pandagl
|
||||
|
||||
#define SOURCES pandagl.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/pandagl/pandagl.cxx
Normal file
9
panda/metalibs/pandagl/pandagl.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: pandagl.cxx
|
||||
// Created by: drose (15May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpandagl.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpandagl.
|
||||
21
panda/metalibs/pandaglut/Sources.pp
Normal file
21
panda/metalibs/pandaglut/Sources.pp
Normal file
@@ -0,0 +1,21 @@
|
||||
#define DIRECTORY_IF_GLUT yes
|
||||
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDAGLUT
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
glutdisplay // sgiglutdisplay
|
||||
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET pandaglut
|
||||
|
||||
#define SOURCES pandaglut.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/pandaglut/pandaglut.cxx
Normal file
9
panda/metalibs/pandaglut/pandaglut.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: pandaglut.cxx
|
||||
// Created by: drose (15May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpandaglut.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpandaglut.
|
||||
19
panda/metalibs/pandaphysics/Sources.pp
Normal file
19
panda/metalibs/pandaphysics/Sources.pp
Normal file
@@ -0,0 +1,19 @@
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDAPHYSICS
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
physics particlesystem
|
||||
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET pandaphysics
|
||||
|
||||
#define SOURCES pandaphysics.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/pandaphysics/pandaphysics.cxx
Normal file
9
panda/metalibs/pandaphysics/pandaphysics.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: pandaphysics.cxx
|
||||
// Created by: drose (16May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpandaphysics.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpandaphysics.
|
||||
21
panda/metalibs/pandarib/Sources.pp
Normal file
21
panda/metalibs/pandarib/Sources.pp
Normal file
@@ -0,0 +1,21 @@
|
||||
#define DIRECTORY_IF_RIB yes
|
||||
|
||||
// DIR_TYPE "metalib" indicates we are building a shared library that
|
||||
// consists mostly of references to other shared libraries. Under
|
||||
// Windows, this directly produces a DLL (as opposed to the regular
|
||||
// src libraries, which don't produce anything but a pile of OBJ files
|
||||
// under Windows).
|
||||
|
||||
#define DIR_TYPE metalib
|
||||
#define BUILDING_DLL BUILDING_PANDARIB
|
||||
|
||||
#define LOCAL_LIBS \
|
||||
ribgsg ribdisplay
|
||||
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin metalib_target
|
||||
#define TARGET pandarib
|
||||
|
||||
#define SOURCES pandarib.cxx
|
||||
#end metalib_target
|
||||
9
panda/metalibs/pandarib/pandarib.cxx
Normal file
9
panda/metalibs/pandarib/pandarib.cxx
Normal file
@@ -0,0 +1,9 @@
|
||||
// Filename: pandarib.cxx
|
||||
// Created by: drose (15May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a dummy file whose sole purpose is to give the compiler
|
||||
// something to compile when making libpandarib.so in NO_DEFER mode,
|
||||
// which generates an empty library that itself links with all the
|
||||
// other shared libraries that make up libpandarib.
|
||||
212
panda/src/PACKAGE-DESC
Normal file
212
panda/src/PACKAGE-DESC
Normal file
@@ -0,0 +1,212 @@
|
||||
Quick descriptions of the packages:
|
||||
|
||||
audio -
|
||||
Audio API for panda
|
||||
builder -
|
||||
A tool to create Geoms and GeomNodes from a pile of unconnected
|
||||
triangles or polygons. It separates geometry according to state
|
||||
(texturing, normals, etc.), discovers connections where they exist
|
||||
and tries to build nearly-optimal tristrips.
|
||||
chan -
|
||||
Animation channels. This defines the various kinds of
|
||||
AnimChannels that may be defined, as well as the MovingPart class
|
||||
which binds to the channels and plays the animation. This is a
|
||||
support library for char, as well as any other libraries that want
|
||||
to define objects whose values change over time.
|
||||
chancfg -
|
||||
This package contains the code for the 'channel configuration' system.
|
||||
This is responsible for asking for a window to be opened, possibly binding
|
||||
'pipe video' channels to it, and dividing it up into Display Regions.
|
||||
chat -
|
||||
Implementation of a text-entry system along the bottom edge of the
|
||||
window, along with any other support functions for an online chat
|
||||
system that might be required.
|
||||
collide -
|
||||
This package contains the classes that control and detect collisions
|
||||
configfiles -
|
||||
This package contains the housekeeping and configuration files needed by
|
||||
things like attach, and emacs.
|
||||
cull -
|
||||
This package contains the Cull Traverser. The cull traversal collects all
|
||||
state changes specified, and removes unneccesary state change requests. Also
|
||||
does all the depth sorting for proper alphaing.
|
||||
device -
|
||||
Device drivers, such as mouse and keyboard, trackers, etc... The
|
||||
base class for using various device APIs is here.
|
||||
dgraph -
|
||||
Defines and manages the data graph, which is the hierarchy of
|
||||
devices, tforms, and any other things which might have an input or
|
||||
an output and need to execute every frame.
|
||||
display -
|
||||
Abstract display classes, including pipes, windows, channels, and
|
||||
display regions
|
||||
doc -
|
||||
Documentation that doesn't fit in any of the packages
|
||||
downloader -
|
||||
Tool to allow automatic download of files in the background
|
||||
dxgsg -
|
||||
Handles all communication with the DirectX backend, and manages state
|
||||
to minimize redundant state changes.
|
||||
effects -
|
||||
Various graphics effects that aren't shaders. I.E Lens Flares
|
||||
egg -
|
||||
A.k.a. the "egg library", this reads, writes, and manipulates egg
|
||||
files. It knows nothing about the scene graph structure in the
|
||||
rest of the player; it lives in its own little egg world.
|
||||
egg2sg -
|
||||
A.k.a. the "egg loader", this converts the egg structure read from
|
||||
the egg library, above, to a scene graph structure, suitable for
|
||||
rendering.
|
||||
event -
|
||||
Tools for throwing, handling and receiving events
|
||||
framework -
|
||||
A simple, stupid framework around which to write a simple, stupid
|
||||
demo program. Handy for quickly writing programs that open a
|
||||
window and display the OmniTriangle.
|
||||
glgsg -
|
||||
Handles all communication with the GL backend, and manages state
|
||||
to minimize redundant state changes.
|
||||
glidedisplay - (defunct)
|
||||
This package contains the code to manage pipes/windows/channels on glide
|
||||
hardware.
|
||||
glidegsg - (defunct)
|
||||
This package contains the GSG for the glide backend. All glide calls
|
||||
should live in here.
|
||||
glutdisplay -
|
||||
Glut specific display classes. This uses the Glut library to open
|
||||
a window and manage keyboard and mouse events. Glut has the
|
||||
advantage of being widely ported, but unfortunately it needs to
|
||||
control the main loop and so limits the kind of programs you can
|
||||
write.
|
||||
glxdisplay -
|
||||
X windows display classes that replace Glut functionality.
|
||||
gobj -
|
||||
Graphical non-scene-graph objects, such as textures and geometry primitives
|
||||
graph -
|
||||
Defines the basic graph operations that are not specific to scene
|
||||
graphs. This includes nodes, relations, transitions, and
|
||||
attributes.
|
||||
gsg -
|
||||
The base definition for the GraphicsStateGuardian. This is the
|
||||
abstract base class for all backend specifications.
|
||||
gsgbase -
|
||||
Base GSG class defined to avoid cyclical dependency build
|
||||
gsgmisc -
|
||||
Some utility functions for gsg that could not live in the same
|
||||
directory for circular dependency reasons.
|
||||
ipc -
|
||||
This package contains the abstraction/adaptation layer for: mutexes,
|
||||
semiphores, condition variables, threads, and files.
|
||||
light -
|
||||
Lights needed to be their own package to avoid multiple inheritance
|
||||
problems. All concrete light types are both lights and nodes.
|
||||
linmath -
|
||||
Linear algebra library.
|
||||
loader -
|
||||
Tool for loading various kinds of files into Graph structures.
|
||||
Can be done asynchronously
|
||||
mathutil -
|
||||
Math utility functions, such as frustum and plane
|
||||
net -
|
||||
Net connection classes
|
||||
panda -
|
||||
Builds the libpanda shared library. This is a single library that
|
||||
encapsulates most of the packages in Panda, especially those that
|
||||
are considered essential to Panda's basic functionality. On
|
||||
Windows platforms, the individual packages are not themselves
|
||||
built into shared libraries; the single LIBPANDA.DLL is the only
|
||||
library file. On Unix platforms, the individual packages are each
|
||||
built into their own shared library files, and a trivial
|
||||
libpanda.so is built that unifies all of them.
|
||||
pandadx -
|
||||
As above, for the DirectX libraries. This includes all of the
|
||||
packages, in addition to those in libpanda, that are required for
|
||||
rendering on a DirectX platform. This also includes
|
||||
Windows-specific libraries.
|
||||
pandaegg -
|
||||
As above, for the egg reader. This includes all of the packages,
|
||||
in addition to those in libpanda, that are required for reading
|
||||
egg files into the scene graph.
|
||||
pandagl -
|
||||
As above, for the OpenGL libraries. This includes all of the
|
||||
packages, in addition to those in libpanda, that are required for
|
||||
rendering on an OpenGL platform, with the exception of Glut.
|
||||
pandaglut -
|
||||
As above, for the OpenGL Glut libraries.
|
||||
pandaphysics -
|
||||
As above, for the physics/particle systems libraries.
|
||||
pandarib -
|
||||
As above, for the Renderman non-realtime renderer.
|
||||
particlesystem -
|
||||
Tool for doing particle systems. Contains various kinds of particles,
|
||||
emiters, factories and renderers.
|
||||
physics -
|
||||
Base classes for physical objects and forces. Also contains the
|
||||
physics manager class
|
||||
pnm -
|
||||
A more-or-less intact version of the NetPBM package, compiled as a
|
||||
single library. This is a support library for pnmimage.
|
||||
pnmimage -
|
||||
Reads and writes image files in various formats, by using the pnm
|
||||
and tiff libraries.
|
||||
pstats -
|
||||
Package for gathering performance statistics
|
||||
ps2display - (defunct)
|
||||
Playstation 2 display classes.
|
||||
p2gsg - (defunct)
|
||||
Play station 2 specific rendering backend.
|
||||
ribdisplay -
|
||||
RIB-specific "display" classes. These don't actually open
|
||||
windows, but actually specify filenames.
|
||||
ribgsg -
|
||||
The RIB-specific rendering backend. Writing a frame to this
|
||||
backend causes a RIB file to be produced, which can be used to
|
||||
render the scene offline.
|
||||
sgattrib -
|
||||
Scene graph attributes and transitions (state information)
|
||||
sgidisplay -
|
||||
This package contains the code to manage pipes/windows/channels on SGI
|
||||
hardware.
|
||||
sgiglutdisplay -
|
||||
This package contains the code to manage pipes/windows/channels on SGI
|
||||
hardware for GLUT
|
||||
sgiglxdisplay -
|
||||
SGI specific X windows display classes that replace Glut functionality.
|
||||
sgmanip -
|
||||
High-level tools for manipulation of scene graphs. This primarily
|
||||
defines NodePath, the principle interface for high-level scripting
|
||||
languages into the scene graph.
|
||||
sgraph -
|
||||
Graph operations and nodes that are specific to render-type scene
|
||||
graphs. This includes GeomNode, Camera, etc.
|
||||
sgraphutil -
|
||||
Handy utility functions for working with scene graphs.
|
||||
shader -
|
||||
Shaders that generate special effects by modifying the render
|
||||
traversal and computing multiple passes.
|
||||
stats - (defunct)
|
||||
Package for gathering performance stats
|
||||
statsdisplay - (defunct)
|
||||
Package for remotely displaying the perfomance stats on a running program
|
||||
switchnode -
|
||||
Package of nodes that switch out geometry underneath them based on
|
||||
various conditions.
|
||||
testbed -
|
||||
C test programs, that primarily link with framework.
|
||||
text -
|
||||
Package for generating renderable text using textured polygons.
|
||||
tform -
|
||||
Data transforming objects that live in the data graph and convert
|
||||
raw data (as read from an input device, for instance) to something
|
||||
more useful.
|
||||
tiff -
|
||||
Another support library for pnmimage.
|
||||
util -
|
||||
This package contains all the little fiddley things that are atomic to
|
||||
just about all the code. Things like: config, ref count, notify, etc.
|
||||
vrpn -
|
||||
Defines the specific client code for interfacing to the VRPN API.
|
||||
wdxdisplay -
|
||||
Windows DirectX specific display classes
|
||||
wgldisplay -
|
||||
Windows OpenGL specific display classes
|
||||
4
panda/src/Sources.pp
Normal file
4
panda/src/Sources.pp
Normal file
@@ -0,0 +1,4 @@
|
||||
// This is a group directory: a directory level above a number of
|
||||
// source subdirectories.
|
||||
|
||||
#define DIR_TYPE group
|
||||
49
panda/src/audio/Sources.pp
Normal file
49
panda/src/audio/Sources.pp
Normal file
@@ -0,0 +1,49 @@
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET audio
|
||||
#define LOCAL_LIBS putil ipc
|
||||
|
||||
#define SOURCES \
|
||||
audio_manager.I audio_manager.cxx audio_manager.h audio_midi.cxx \
|
||||
audio_midi.h audio_music.I audio_music.cxx audio_music.h \
|
||||
audio_pool.I audio_pool.cxx audio_pool.h audio_sample.I \
|
||||
audio_sample.cxx audio_sample.h audio_trait.cxx audio_trait.h \
|
||||
config_audio.cxx config_audio.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
audio.h audio_manager.h audio_music.h audio_pool.I audio_pool.h \
|
||||
audio_sample.I audio_sample.h audio_trait.h
|
||||
|
||||
#define IGATESCAN audio.h
|
||||
|
||||
#end lib_target
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET audio_load_midi
|
||||
#define LOCAL_LIBS \
|
||||
audio
|
||||
|
||||
#define SOURCES \
|
||||
audio_load_midi.cxx
|
||||
|
||||
#end lib_target
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET audio_load_wav
|
||||
#define LOCAL_LIBS \
|
||||
audio
|
||||
|
||||
#define SOURCES \
|
||||
audio_load_wav.cxx
|
||||
|
||||
#end lib_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_audio
|
||||
|
||||
#define SOURCES \
|
||||
test_audio.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
15
panda/src/audio/audio.h
Normal file
15
panda/src/audio/audio.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Filename: audio.h
|
||||
// Created by: frang (06Jul00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_H__
|
||||
#define __AUDIO_H__
|
||||
|
||||
#include "audio_trait.h"
|
||||
#include "audio_sample.h"
|
||||
#include "audio_music.h"
|
||||
#include "audio_manager.h"
|
||||
#include "audio_pool.h"
|
||||
|
||||
#endif /* __AUDIO_H__ */
|
||||
75
panda/src/audio/audio_load_midi.cxx
Normal file
75
panda/src/audio/audio_load_midi.cxx
Normal file
@@ -0,0 +1,75 @@
|
||||
// Filename: audio_load_midi.cxx
|
||||
// Created by: cary (26Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <dconfig.h>
|
||||
#include "audio_pool.h"
|
||||
#include "config_audio.h"
|
||||
|
||||
Configure(audio_load_midi);
|
||||
|
||||
#ifdef USE_MIKMOD
|
||||
|
||||
#include "audio_mikmod_traits.h"
|
||||
|
||||
void AudioDestroyMidi(AudioTraits::MusicClass* music) {
|
||||
MikModMidi::destroy(music);
|
||||
}
|
||||
|
||||
void AudioLoadMidi(AudioTraits::MusicClass** music,
|
||||
AudioTraits::PlayerClass** player,
|
||||
AudioTraits::DeleteMusicFunc** destroy, Filename filename) {
|
||||
*music = MikModMidi::load_midi(filename);
|
||||
if (*music == (AudioTraits::MusicClass*)0L)
|
||||
return;
|
||||
*player = MikModMidiPlayer::get_instance();
|
||||
*destroy = AudioDestroyMidi;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef PENV_WIN32
|
||||
|
||||
#include "audio_win_traits.h"
|
||||
|
||||
void AudioDestroyMidi(AudioTraits::MusicClass* music) {
|
||||
WinMusic::destroy(music);
|
||||
}
|
||||
|
||||
void AudioLoadMidi(AudioTraits::MusicClass** music,
|
||||
AudioTraits::PlayerClass** player,
|
||||
AudioTraits::DeleteMusicFunc** destroy, Filename filename) {
|
||||
*music = WinMusic::load_midi(filename);
|
||||
if (*music == (AudioTraits::MusicClass*)0L)
|
||||
return;
|
||||
*player = WinPlayer::get_instance();
|
||||
*destroy = AudioDestroyMidi;
|
||||
audio_cat->debug() << "sanity check: music = " << (void*)*music
|
||||
<< " player = " << (void*)*player << " destroy = "
|
||||
<< (void*)*destroy << endl;
|
||||
}
|
||||
#else
|
||||
|
||||
// Null driver
|
||||
#include "audio_null_traits.h"
|
||||
|
||||
void AudioDestroyMidi(AudioTraits::MusicClass* music) {
|
||||
delete music;
|
||||
}
|
||||
|
||||
void AudioLoadMidi(AudioTraits::MusicClass** music,
|
||||
AudioTraits::PlayerClass** player,
|
||||
AudioTraits::DeleteMusicFunc** destroy, Filename) {
|
||||
*music = new NullMusic();
|
||||
*player = new NullPlayer();
|
||||
*destroy = AudioDestroyMidi;
|
||||
}
|
||||
|
||||
#endif /* win32 */
|
||||
#endif /* mikmod */
|
||||
|
||||
ConfigureFn(audio_load_midi) {
|
||||
AudioPool::register_music_loader("midi", AudioLoadMidi);
|
||||
AudioPool::register_music_loader("mid", AudioLoadMidi);
|
||||
}
|
||||
71
panda/src/audio/audio_load_wav.cxx
Normal file
71
panda/src/audio/audio_load_wav.cxx
Normal file
@@ -0,0 +1,71 @@
|
||||
// Filename: audio_load_wav.cxx
|
||||
// Created by: cary (23Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <dconfig.h>
|
||||
#include "audio_pool.h"
|
||||
|
||||
Configure(audio_load_wav);
|
||||
|
||||
#ifdef USE_MIKMOD
|
||||
|
||||
#include "audio_mikmod_traits.h"
|
||||
|
||||
void AudioDestroyWav(AudioTraits::SampleClass* sample) {
|
||||
MikModSample::destroy(sample);
|
||||
}
|
||||
|
||||
void AudioLoadWav(AudioTraits::SampleClass** sample,
|
||||
AudioTraits::PlayerClass** player,
|
||||
AudioTraits::DeleteSampleFunc** destroy, Filename filename) {
|
||||
*sample = MikModSample::load_wav(filename);
|
||||
if (*sample == (AudioTraits::SampleClass*)0L)
|
||||
return;
|
||||
*player = MikModSamplePlayer::get_instance();
|
||||
*destroy = AudioDestroyWav;
|
||||
}
|
||||
|
||||
#else /* no MikMod */
|
||||
|
||||
#ifdef PENV_WIN32
|
||||
|
||||
#include "audio_win_traits.h"
|
||||
|
||||
void AudioDestroyWav(AudioTraits::SampleClass* sample) {
|
||||
WinSample::destroy(sample);
|
||||
}
|
||||
|
||||
void AudioLoadWav(AudioTraits::SampleClass** sample,
|
||||
AudioTraits::PlayerClass** player,
|
||||
AudioTraits::DeleteSampleFunc** destroy, Filename filename) {
|
||||
*sample = WinSample::load_wav(filename);
|
||||
if (*sample == (AudioTraits::SampleClass*)0L)
|
||||
return;
|
||||
*player = WinPlayer::get_instance();
|
||||
*destroy = AudioDestroyWav;
|
||||
}
|
||||
|
||||
#else /* no win32 */
|
||||
|
||||
// Null driver
|
||||
#include "audio_null_traits.h"
|
||||
|
||||
void AudioDestroyWav(AudioTraits::SampleClass* sample) {
|
||||
delete sample;
|
||||
}
|
||||
|
||||
void AudioLoadWav(AudioTraits::SampleClass** sample,
|
||||
AudioTraits::PlayerClass** player,
|
||||
AudioTraits::DeleteSampleFunc** destroy, Filename) {
|
||||
*sample = new NullSample();
|
||||
*player = new NullPlayer();
|
||||
*destroy = AudioDestroyWav;
|
||||
}
|
||||
|
||||
#endif /* win32 */
|
||||
#endif /* MikMod */
|
||||
|
||||
ConfigureFn(audio_load_wav) {
|
||||
AudioPool::register_sample_loader("wav", AudioLoadWav);
|
||||
}
|
||||
69
panda/src/audio/audio_manager.I
Normal file
69
panda/src/audio/audio_manager.I
Normal file
@@ -0,0 +1,69 @@
|
||||
// Filename: audio_manager.I
|
||||
// Created by: cary (24Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::play (AudioSample)
|
||||
// Access: Public, Static
|
||||
// Description: Play an audio sample
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioManager::play(AudioSample* sample) {
|
||||
get_ptr()->ns_play(sample);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::play (AudioMusic)
|
||||
// Access: Public, Static
|
||||
// Description: Play an audio music instance
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioManager::play(AudioMusic* music) {
|
||||
get_ptr()->ns_play(music);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::update
|
||||
// Access: Public, Static
|
||||
// Description: make sure buffers are full
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioManager::update(void) {
|
||||
mutex_lock l(_manager_mutex);
|
||||
if (_update_func != (UpdateFunc*)0L)
|
||||
(*_update_func)();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::spawn_update
|
||||
// Access: Public, Static
|
||||
// Description: spawn a thread to call update
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioManager::spawn_update(void) {
|
||||
get_ptr()->ns_spawn_update();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::set_volume (sample)
|
||||
// Access: Public, Static
|
||||
// Description: set the volume on a sample
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioManager::set_volume(AudioSample* sample, int v) {
|
||||
get_ptr()->ns_set_volume(sample, v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::set_volume (music)
|
||||
// Access: Public, Static
|
||||
// Description: set the volume on music
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioManager::set_volume(AudioMusic* music, int v) {
|
||||
get_ptr()->ns_set_volume(music, v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::Constructor
|
||||
// Access: Private
|
||||
// Description: The constructor is not intended to be called
|
||||
// directly; there's only supposed to be one AudioManager
|
||||
// in the universe and it constructs itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioManager::AudioManager(void) : _spawned((thread*)0L) {}
|
||||
95
panda/src/audio/audio_manager.cxx
Normal file
95
panda/src/audio/audio_manager.cxx
Normal file
@@ -0,0 +1,95 @@
|
||||
// Filename: audio_manager.cxx
|
||||
// Created by: cary (24Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_manager.h"
|
||||
#include "config_audio.h"
|
||||
|
||||
AudioManager* AudioManager::_global_ptr = (AudioManager*)0L;
|
||||
AudioManager::UpdateFunc* AudioManager::_update_func =
|
||||
(AudioManager::UpdateFunc*)0L;
|
||||
mutex AudioManager::_manager_mutex;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::set_update_func
|
||||
// Access: Public, Static
|
||||
// Description: register a function that will maintain the buffers
|
||||
// for audio output
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::set_update_func(AudioManager::UpdateFunc* func) {
|
||||
if (_update_func != (AudioManager::UpdateFunc*)0L)
|
||||
audio_cat->error() << "There maybe be more then one audio driver installed"
|
||||
<< endl;
|
||||
_update_func = func;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::get_ptr
|
||||
// Access: Private, Static
|
||||
// Description: Initializes and/or returns the global pointer to the
|
||||
// one AudioManager object in the system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioManager* AudioManager::get_ptr(void) {
|
||||
if (_global_ptr == (AudioManager*)0L)
|
||||
_global_ptr = new AudioManager;
|
||||
return _global_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::ns_play (AudioSample)
|
||||
// Access: Private
|
||||
// Description: get the player off the sample, and start it playing
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::ns_play(AudioSample* sample) {
|
||||
sample->get_player()->play_sample(sample->get_sample());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::ns_play (AudioMusic)
|
||||
// Access: Private
|
||||
// Description: get the player off the music, and start it playing
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::ns_play(AudioMusic* music) {
|
||||
music->get_player()->play_music(music->get_music());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::spawned_update
|
||||
// Access: static
|
||||
// Description: the thread function to call update forever.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::spawned_update(void*) {
|
||||
while (1) {
|
||||
AudioManager::update();
|
||||
ipc_traits::sleep(0, 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::ns_set_volume (AudioSample)
|
||||
// Access: Private
|
||||
// Description: get the player off the sample, and set volume on it
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::ns_set_volume(AudioSample* sample, int v) {
|
||||
sample->get_player()->set_volume(sample->get_sample(), v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::ns_set_volume (AudioMusic)
|
||||
// Access: Private
|
||||
// Description: get the player off the music, and set volume on it
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::ns_set_volume(AudioMusic* music, int v) {
|
||||
music->get_player()->set_volume(music->get_music(), v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::ns_spawn_update
|
||||
// Access: Private
|
||||
// Description: spawn a thread that calls update every so often
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::ns_spawn_update(void) {
|
||||
_spawned = thread::create(spawned_update, (void*)0L,
|
||||
thread::PRIORITY_NORMAL);
|
||||
}
|
||||
47
panda/src/audio/audio_manager.h
Normal file
47
panda/src/audio/audio_manager.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Filename: audio_manager.h
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_MANAGER_H__
|
||||
#define __AUDIO_MANAGER_H__
|
||||
|
||||
#include "audio_trait.h"
|
||||
#include "audio_sample.h"
|
||||
#include "audio_music.h"
|
||||
|
||||
#include <ipc_mutex.h>
|
||||
#include <ipc_thread.h>
|
||||
|
||||
class EXPCL_PANDA AudioManager {
|
||||
private:
|
||||
INLINE AudioManager(void);
|
||||
|
||||
void ns_play(AudioSample*);
|
||||
void ns_play(AudioMusic*);
|
||||
void ns_spawn_update(void);
|
||||
void ns_set_volume(AudioSample*, int);
|
||||
void ns_set_volume(AudioMusic*, int);
|
||||
|
||||
static AudioManager* get_ptr(void);
|
||||
static void spawned_update(void*);
|
||||
|
||||
typedef void UpdateFunc(void);
|
||||
static AudioManager* _global_ptr;
|
||||
static UpdateFunc* _update_func;
|
||||
static mutex _manager_mutex;
|
||||
thread* _spawned;
|
||||
public:
|
||||
static void set_update_func(UpdateFunc*);
|
||||
|
||||
INLINE static void play(AudioSample*);
|
||||
INLINE static void play(AudioMusic*);
|
||||
INLINE static void update(void);
|
||||
INLINE static void spawn_update(void);
|
||||
INLINE static void set_volume(AudioSample*, int);
|
||||
INLINE static void set_volume(AudioMusic*, int);
|
||||
};
|
||||
|
||||
#include "audio_manager.I"
|
||||
|
||||
#endif /* __AUDIO_MANAGER_H__ */
|
||||
233
panda/src/audio/audio_midi.cxx
Normal file
233
panda/src/audio/audio_midi.cxx
Normal file
@@ -0,0 +1,233 @@
|
||||
// Filename: audio_midi.cxx
|
||||
// Created by: cary (26Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_midi.h"
|
||||
#include "config_audio.h"
|
||||
#include <pandabase.h> // get iostream and fstream
|
||||
|
||||
#define SHORT short
|
||||
#define LONG long
|
||||
|
||||
#define RIFF 0x52494646
|
||||
#define CTMF 0x43544d46
|
||||
#define MThd 0x4d546864
|
||||
#define MTrk 0x4d54726b
|
||||
|
||||
// take data off the supplimental stream until it's empty
|
||||
inline static unsigned char read8(istream& is, istream& supp) {
|
||||
unsigned char b;
|
||||
if (supp.eof()) {
|
||||
is >> b;
|
||||
} else {
|
||||
supp >> b;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
inline static unsigned SHORT read16(istream& is, istream& supp) {
|
||||
unsigned char b1, b2;
|
||||
b1 = read8(is, supp);
|
||||
b2 = read8(is, supp);
|
||||
unsigned SHORT ret = (b1 << 8) | (b2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static unsigned LONG read32(istream& is, istream& supp) {
|
||||
unsigned char b1, b2, b3, b4;
|
||||
b1 = read8(is, supp);
|
||||
b2 = read8(is, supp);
|
||||
b3 = read8(is, supp);
|
||||
b4 = read8(is, supp);
|
||||
unsigned int LONG ret = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline static void scroll8(unsigned LONG& prev, unsigned LONG& curr,
|
||||
istream& is, istream& supp) {
|
||||
unsigned char b1 = ((curr >> 24) & 0xff);
|
||||
prev = ((prev << 8) & 0xffffff00) | (b1);
|
||||
b1 = read8(is, supp);
|
||||
curr = ((curr << 8) & 0xffffff00) | (b1);
|
||||
}
|
||||
|
||||
AudioMidi::AudioMidi(Filename filename, int header_idx) {
|
||||
filename.set_binary();
|
||||
ifstream in;
|
||||
if (!filename.open_read(in)) {
|
||||
cerr << "ACK, cannot read '" << filename << "'" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
istringstream dummy("");
|
||||
unsigned LONG prev = 0x0;
|
||||
unsigned LONG curr = read32(in, dummy);
|
||||
int count = 0;
|
||||
bool done = false;
|
||||
do {
|
||||
if (curr == MThd) {
|
||||
++count;
|
||||
if (count == header_idx)
|
||||
done = true;
|
||||
else {
|
||||
scroll8(prev, curr, in, dummy);
|
||||
scroll8(prev, curr, in, dummy);
|
||||
scroll8(prev, curr, in, dummy);
|
||||
scroll8(prev, curr, in, dummy);
|
||||
}
|
||||
} else {
|
||||
scroll8(prev, curr, in, dummy);
|
||||
}
|
||||
if (in.eof())
|
||||
done = true;
|
||||
} while (!done);
|
||||
if (in.eof()) {
|
||||
cerr << "fewer then " << header_idx << " headers in file (" << count
|
||||
<< ")" << endl;
|
||||
return;
|
||||
}
|
||||
if (prev == RIFF) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "it's a RIFF file" << endl;
|
||||
curr = read32(in, dummy);
|
||||
curr = read32(in, dummy);
|
||||
curr = read32(in, dummy);
|
||||
curr = read32(in, dummy);
|
||||
}
|
||||
unsigned LONG tracklen;
|
||||
unsigned SHORT format;
|
||||
unsigned SHORT numtracks;
|
||||
unsigned SHORT division;
|
||||
if (curr == MThd) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "easy header" << endl;
|
||||
tracklen = read32(in, dummy);
|
||||
format = read16(in, dummy);
|
||||
numtracks = read16(in, dummy);
|
||||
division = read16(in, dummy);
|
||||
} else if (curr == CTMF) {
|
||||
// Creative Labs CMF file. We're not supporting this yet
|
||||
cerr << "don't support Creative Labs CMF files yet" << endl;
|
||||
return;
|
||||
} else {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "hard header" << endl;
|
||||
done = false;
|
||||
do {
|
||||
if (curr == MThd)
|
||||
done = true;
|
||||
else
|
||||
scroll8(prev, curr, in, dummy);
|
||||
if (in.eof())
|
||||
done = true;
|
||||
} while (!done);
|
||||
if (in.eof()) {
|
||||
cerr << "truncated file!" << endl;
|
||||
return;
|
||||
}
|
||||
tracklen = read32(in, dummy);
|
||||
format = read16(in, dummy);
|
||||
numtracks = read16(in, dummy);
|
||||
division = read16(in, dummy);
|
||||
}
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "Read header. tracklen = " << tracklen
|
||||
<< " format = " << format << " numtracks = "
|
||||
<< numtracks << " division = " << division << endl;
|
||||
for (int currtrack = 0; currtrack < numtracks; ++currtrack) {
|
||||
string fudge;
|
||||
curr = read32(in, dummy);
|
||||
if (curr != MTrk) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "having to seach for track #" << currtrack
|
||||
<< endl;
|
||||
if (curr == MThd) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "hit a header instead, skipping track" << endl;
|
||||
continue;
|
||||
} else {
|
||||
done = false;
|
||||
if (currtrack > 0) {
|
||||
string stmp = (*(_seq.rbegin()));
|
||||
int i = stmp.rfind("MTrk");
|
||||
if (i != string::npos) {
|
||||
fudge = stmp.substr(i+4, string::npos);
|
||||
unsigned char b;
|
||||
b = ((curr >> 24) & 0xff);
|
||||
fudge += b;
|
||||
b = ((curr >> 16) & 0xff);
|
||||
fudge += b;
|
||||
b = ((curr >> 8) & 0xff);
|
||||
fudge += b;
|
||||
b = (curr & 0xff);
|
||||
fudge += b;
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
do {
|
||||
if (curr == MTrk)
|
||||
done = true;
|
||||
else
|
||||
scroll8(prev, curr, in, dummy);
|
||||
if (in.eof())
|
||||
done = true;
|
||||
} while (!done);
|
||||
if (in.eof()) {
|
||||
cerr << "truncated file" << endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "fudge = '" << fudge << "'" << endl;
|
||||
istringstream fudges(fudge);
|
||||
if (fudge.empty()) {
|
||||
// force EOF
|
||||
unsigned char b;
|
||||
fudges >> b;
|
||||
}
|
||||
unsigned LONG thislen = read32(in, fudges);
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "found track #" << currtrack << " with length = "
|
||||
<< thislen << endl;
|
||||
{
|
||||
ostringstream os;
|
||||
int i;
|
||||
for (i=0; i<thislen; ++i) {
|
||||
unsigned char b;
|
||||
b = read8(in, fudges);
|
||||
os << b;
|
||||
if (in.eof() && ((i+1) < thislen))
|
||||
break;
|
||||
}
|
||||
if (in.eof() && (i != thislen)) {
|
||||
cerr << "truncated file" << endl;
|
||||
}
|
||||
string s = os.str();
|
||||
_seq.push_back(s);
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "track data (" << s.length() << "): '" << s
|
||||
<< "'" << endl;
|
||||
}
|
||||
}
|
||||
if ((_seq.size() != numtracks) && audio_cat->is_debug())
|
||||
audio_cat->debug()
|
||||
<< "actual number of tracks read does not match header. ("
|
||||
<< _seq.size() << " != " << numtracks << ")" << endl;
|
||||
}
|
||||
|
||||
AudioMidi::AudioMidi(const AudioMidi& c) : _seq(c._seq) {}
|
||||
|
||||
AudioMidi::~AudioMidi(void) {
|
||||
}
|
||||
|
||||
AudioMidi& AudioMidi::operator=(const AudioMidi&) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool AudioMidi::operator==(const AudioMidi&) const {
|
||||
return false;
|
||||
}
|
||||
26
panda/src/audio/audio_midi.h
Normal file
26
panda/src/audio/audio_midi.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Filename: audio_midi.h
|
||||
// Created by: cary (26Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_MIDI_H__
|
||||
#define __AUDIO_MIDI_H__
|
||||
|
||||
#include <filename.h>
|
||||
#include <list>
|
||||
|
||||
// define an internal representation for a midi file
|
||||
class AudioMidi {
|
||||
private:
|
||||
typedef list<string> StrList;
|
||||
StrList _seq;
|
||||
public:
|
||||
AudioMidi(Filename, int = 1);
|
||||
AudioMidi(const AudioMidi&);
|
||||
~AudioMidi(void);
|
||||
|
||||
AudioMidi& operator=(const AudioMidi&);
|
||||
bool operator==(const AudioMidi&) const;
|
||||
};
|
||||
|
||||
#endif /* __AUDIO_MIDI_H__ */
|
||||
305
panda/src/audio/audio_mikmod_traits.cxx
Normal file
305
panda/src/audio/audio_mikmod_traits.cxx
Normal file
@@ -0,0 +1,305 @@
|
||||
// Filename: audio_mikmod_traits.cxx
|
||||
// Created by: cary (23Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_mikmod_traits.h"
|
||||
#include "audio_manager.h"
|
||||
#include "config_audio.h"
|
||||
#include <list>
|
||||
#include <serialization.h>
|
||||
|
||||
static bool have_initialized = false;
|
||||
static bool initialization_error = false;
|
||||
|
||||
static void update_mikmod(void) {
|
||||
MikMod_Update();
|
||||
}
|
||||
|
||||
static void initialize(void) {
|
||||
if (have_initialized)
|
||||
return;
|
||||
if (initialization_error)
|
||||
return;
|
||||
/* register the drivers */
|
||||
MikMod_RegisterAllDrivers();
|
||||
/* initialize the mikmod library */
|
||||
md_mixfreq = audio_mix_freq;
|
||||
{
|
||||
// I think this is defined elsewhere
|
||||
typedef list<string> StrList;
|
||||
typedef Serialize::Deserializer<StrList> OptBuster;
|
||||
StrList opts;
|
||||
OptBuster buster(*audio_mode_flags, " ");
|
||||
opts = buster();
|
||||
for (StrList::iterator i=opts.begin(); i!=opts.end(); ++i) {
|
||||
if ((*i) == "DMODE_INTERP") {
|
||||
md_mode |= DMODE_INTERP;
|
||||
} else if ((*i) == "DMODE_REVERSE") {
|
||||
md_mode |= DMODE_REVERSE;
|
||||
} else if ((*i) == "DMODE_SURROUND") {
|
||||
md_mode |= DMODE_SURROUND;
|
||||
} else if ((*i) == "DMODE_16BITS") {
|
||||
md_mode |= DMODE_16BITS;
|
||||
} else if ((*i) == "DMODE_HQMIXER") {
|
||||
md_mode |= DMODE_HQMIXER;
|
||||
} else if ((*i) == "DMODE_SOFT_MUSIC") {
|
||||
md_mode |= DMODE_SOFT_MUSIC;
|
||||
} else if ((*i) == "DMODE_SOFT_SNDFX") {
|
||||
md_mode |= DMODE_SOFT_SNDFX;
|
||||
} else if ((*i) == "DMODE_STEREO") {
|
||||
md_mode |= DMODE_STEREO;
|
||||
} else {
|
||||
audio_cat->error() << "unknown audio driver flag '" << *i << "'"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
if (audio_cat->is_debug()) {
|
||||
audio_cat->debug() << "final driver mode is (";
|
||||
bool any_out = false;
|
||||
if (md_mode & DMODE_INTERP) {
|
||||
audio_cat->debug(false) << "DMODE_INTERP";
|
||||
any_out = true;
|
||||
}
|
||||
if (md_mode & DMODE_REVERSE) {
|
||||
if (any_out)
|
||||
audio_cat->debug(false) << ", ";
|
||||
audio_cat->debug(false) << "DMODE_REVERSE";
|
||||
any_out = true;
|
||||
}
|
||||
if (md_mode & DMODE_SURROUND) {
|
||||
if (any_out)
|
||||
audio_cat->debug(false) << ", ";
|
||||
audio_cat->debug(false) << "DMODE_SURROUND";
|
||||
any_out = true;
|
||||
}
|
||||
if (md_mode & DMODE_16BITS) {
|
||||
if (any_out)
|
||||
audio_cat->debug(false) << ", ";
|
||||
audio_cat->debug(false) << "DMODE_16BITS";
|
||||
any_out = true;
|
||||
}
|
||||
if (md_mode & DMODE_HQMIXER) {
|
||||
if (any_out)
|
||||
audio_cat->debug(false) << ", ";
|
||||
audio_cat->debug(false) << "DMODE_HQMIXER";
|
||||
any_out = true;
|
||||
}
|
||||
if (md_mode & DMODE_SOFT_MUSIC) {
|
||||
if (any_out)
|
||||
audio_cat->debug(false) << ", ";
|
||||
audio_cat->debug(false) << "DMODE_SOFT_MUSIC";
|
||||
any_out = true;
|
||||
}
|
||||
if (md_mode & DMODE_SOFT_SNDFX) {
|
||||
if (any_out)
|
||||
audio_cat->debug(false) << ", ";
|
||||
audio_cat->debug(false) << "DMODE_SOFT_SNDFX";
|
||||
any_out = true;
|
||||
}
|
||||
if (md_mode & DMODE_STEREO) {
|
||||
if (any_out)
|
||||
audio_cat->debug(false) << ", ";
|
||||
audio_cat->debug(false) << "DMODE_STEREO";
|
||||
any_out = true;
|
||||
}
|
||||
audio_cat->debug(false) << ")" << endl;
|
||||
}
|
||||
}
|
||||
md_device = audio_driver_select;
|
||||
if (MikMod_Init((char*)(audio_driver_params->c_str()))) {
|
||||
audio_cat->error() << "Could not initialize the audio drivers. '"
|
||||
<< MikMod_strerror(MikMod_errno) << "'" << endl;
|
||||
initialization_error = true;
|
||||
return;
|
||||
}
|
||||
if (audio_cat->is_debug()) {
|
||||
audio_cat->debug() << "driver info" << endl << MikMod_InfoDriver() << endl;
|
||||
}
|
||||
MikMod_SetNumVoices(-1, audio_sample_voices);
|
||||
AudioManager::set_update_func(update_mikmod);
|
||||
have_initialized = true;
|
||||
}
|
||||
|
||||
MikModSample::MikModSample(SAMPLE* sample) : _sample(sample), _voice(-1) {
|
||||
}
|
||||
|
||||
MikModSample::~MikModSample(void) {
|
||||
Sample_Free(_sample);
|
||||
}
|
||||
|
||||
float MikModSample::length(void) {
|
||||
float len = _sample->length;
|
||||
float speed = _sample->speed;
|
||||
return len / speed;
|
||||
}
|
||||
|
||||
AudioTraits::SampleClass::SampleStatus MikModSample::status(void) {
|
||||
if (_voice == -1)
|
||||
return READY;
|
||||
if (Voice_Stopped(_voice))
|
||||
return PLAYING;
|
||||
return READY;
|
||||
}
|
||||
|
||||
MikModSample* MikModSample::load_wav(Filename filename) {
|
||||
initialize();
|
||||
SAMPLE* sample = Sample_Load((char*)(filename.c_str()));
|
||||
if (sample == (SAMPLE*)0L) {
|
||||
audio_cat->error() << "error loading sample '" << filename << "' because '"
|
||||
<< MikMod_strerror(MikMod_errno) << "'" << endl;
|
||||
return (MikModSample*)0L;
|
||||
}
|
||||
return new MikModSample(sample);
|
||||
}
|
||||
|
||||
void MikModSample::destroy(AudioTraits::SampleClass* sample) {
|
||||
delete sample;
|
||||
}
|
||||
|
||||
void MikModSample::set_voice(int v) {
|
||||
_voice = v;
|
||||
}
|
||||
|
||||
int MikModSample::get_voice(void) {
|
||||
return _voice;
|
||||
}
|
||||
|
||||
SAMPLE* MikModSample::get_sample(void) {
|
||||
return _sample;
|
||||
}
|
||||
|
||||
int MikModSample::get_freq(void) {
|
||||
return _sample->speed;
|
||||
}
|
||||
|
||||
MikModMusic::MikModMusic(void) {
|
||||
}
|
||||
|
||||
MikModMusic::~MikModMusic(void) {
|
||||
}
|
||||
|
||||
AudioTraits::MusicClass::MusicStatus MikModMusic::status(void) {
|
||||
return READY;
|
||||
}
|
||||
|
||||
MikModMidi::MikModMidi(void) {
|
||||
}
|
||||
|
||||
MikModMidi::~MikModMidi(void) {
|
||||
}
|
||||
|
||||
MikModMidi* MikModMidi::load_midi(Filename) {
|
||||
initialize();
|
||||
return new MikModMidi();
|
||||
}
|
||||
|
||||
void MikModMidi::destroy(AudioTraits::MusicClass* music) {
|
||||
delete music;
|
||||
}
|
||||
|
||||
AudioTraits::MusicClass::MusicStatus MikModMidi::status(void) {
|
||||
return READY;
|
||||
}
|
||||
|
||||
MikModSamplePlayer* MikModSamplePlayer::_global_instance =
|
||||
(MikModSamplePlayer*)0L;
|
||||
|
||||
MikModSamplePlayer::MikModSamplePlayer(void) : AudioTraits::PlayerClass() {
|
||||
}
|
||||
|
||||
MikModSamplePlayer::~MikModSamplePlayer(void) {
|
||||
}
|
||||
|
||||
void MikModSamplePlayer::play_sample(AudioTraits::SampleClass* sample) {
|
||||
if (!have_initialized)
|
||||
initialize();
|
||||
if (!MikMod_Active()) {
|
||||
if (MikMod_EnableOutput()) {
|
||||
audio_cat->error() << "could not enable sample output '"
|
||||
<< MikMod_strerror(MikMod_errno) << "'" << endl;
|
||||
}
|
||||
}
|
||||
// cast to the correct type
|
||||
MikModSample* msample = (MikModSample*)sample;
|
||||
// fire it off
|
||||
msample->set_voice(Sample_Play(msample->get_sample(), 0, 0));
|
||||
Voice_SetFrequency(msample->get_voice(), msample->get_freq());
|
||||
if (Voice_GetFrequency(msample->get_voice()) != msample->get_freq())
|
||||
audio_cat->error() << "setting freq did not stick!" << endl;
|
||||
Voice_SetPanning(msample->get_voice(), 127);
|
||||
}
|
||||
|
||||
void MikModSamplePlayer::play_music(AudioTraits::MusicClass*) {
|
||||
audio_cat->error() << "trying to play music with a MikModSamplePlayer"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void MikModSamplePlayer::set_volume(AudioTraits::SampleClass* sample, int v) {
|
||||
initialize();
|
||||
MikModSample* msample = (MikModSample*)sample;
|
||||
Voice_SetVolume(msample->get_voice(), v);
|
||||
}
|
||||
|
||||
void MikModSamplePlayer::set_volume(AudioTraits::MusicClass*, int) {
|
||||
audio_cat->error()
|
||||
<< "trying to set volume on music withe a MikModSamplePlayer" << endl;
|
||||
}
|
||||
|
||||
MikModSamplePlayer* MikModSamplePlayer::get_instance(void) {
|
||||
if (_global_instance == (MikModSamplePlayer*)0L)
|
||||
_global_instance = new MikModSamplePlayer();
|
||||
return _global_instance;
|
||||
}
|
||||
|
||||
MikModFmsynthPlayer::MikModFmsynthPlayer(void) {
|
||||
}
|
||||
|
||||
MikModFmsynthPlayer::~MikModFmsynthPlayer(void) {
|
||||
}
|
||||
|
||||
void MikModFmsynthPlayer::play_sample(AudioTraits::SampleClass*) {
|
||||
audio_cat->error() << "trying to play a sample with a MikModFmsynthPlayer"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void MikModFmsynthPlayer::play_music(AudioTraits::MusicClass* music) {
|
||||
}
|
||||
|
||||
void MikModFmsynthPlayer::set_volume(AudioTraits::SampleClass*, int) {
|
||||
audio_cat->error()
|
||||
<< "trying to set volume on a sample with a MikModFmsynthPlayer" << endl;
|
||||
}
|
||||
|
||||
void MikModFmsynthPlayer::set_volume(AudioTraits::MusicClass*, int) {
|
||||
}
|
||||
|
||||
MikModMidiPlayer* MikModMidiPlayer::_global_instance = (MikModMidiPlayer*)0L;
|
||||
|
||||
MikModMidiPlayer::MikModMidiPlayer(void) {
|
||||
}
|
||||
|
||||
MikModMidiPlayer::~MikModMidiPlayer(void) {
|
||||
}
|
||||
|
||||
void MikModMidiPlayer::play_sample(AudioTraits::SampleClass*) {
|
||||
audio_cat->error() << "trying to play a sample with a MikModMidiPlayer"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void MikModMidiPlayer::play_music(AudioTraits::MusicClass* music) {
|
||||
}
|
||||
|
||||
void MikModMidiPlayer::set_volume(AudioTraits::SampleClass*, int) {
|
||||
audio_cat->error()
|
||||
<< "trying to set volume on a sample with a MikModMidiPlayer" << endl;
|
||||
}
|
||||
|
||||
void MikModMidiPlayer::set_volume(AudioTraits::MusicClass*, int) {
|
||||
}
|
||||
|
||||
MikModMidiPlayer* MikModMidiPlayer::get_instance(void) {
|
||||
if (_global_instance == (MikModMidiPlayer*)0L)
|
||||
_global_instance = new MikModMidiPlayer();
|
||||
return _global_instance;
|
||||
}
|
||||
102
panda/src/audio/audio_mikmod_traits.h
Normal file
102
panda/src/audio/audio_mikmod_traits.h
Normal file
@@ -0,0 +1,102 @@
|
||||
// Filename: audio_mikmod_traits.h
|
||||
// Created by: frang (06Jul00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_MIKMOD_TRAITS_H__
|
||||
#define __AUDIO_MIKMOD_TRAITS_H__
|
||||
|
||||
#include "audio_trait.h"
|
||||
#include <pandabase.h>
|
||||
#include <filename.h>
|
||||
#include <mikmod.h>
|
||||
|
||||
class EXPCL_PANDA MikModSample : public AudioTraits::SampleClass {
|
||||
private:
|
||||
SAMPLE* _sample;
|
||||
int _voice;
|
||||
|
||||
MikModSample(SAMPLE*);
|
||||
public:
|
||||
virtual ~MikModSample(void);
|
||||
|
||||
virtual float length(void);
|
||||
virtual AudioTraits::SampleClass::SampleStatus status(void);
|
||||
public:
|
||||
// used by the readers
|
||||
static MikModSample* load_wav(Filename);
|
||||
static void destroy(AudioTraits::SampleClass*);
|
||||
// used by the players
|
||||
virtual void set_voice(int);
|
||||
virtual int get_voice(void);
|
||||
virtual SAMPLE* get_sample(void);
|
||||
virtual int get_freq(void);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA MikModMusic : public AudioTraits::MusicClass {
|
||||
private:
|
||||
MODULE* _music;
|
||||
public:
|
||||
MikModMusic(void);
|
||||
virtual ~MikModMusic(void);
|
||||
|
||||
virtual AudioTraits::MusicClass::MusicStatus status(void);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA MikModMidi : public AudioTraits::MusicClass {
|
||||
private:
|
||||
public:
|
||||
MikModMidi(void);
|
||||
virtual ~MikModMidi(void);
|
||||
|
||||
virtual AudioTraits::MusicClass::MusicStatus status(void);
|
||||
public:
|
||||
// used by the readers
|
||||
static MikModMidi* load_midi(Filename);
|
||||
static void destroy(AudioTraits::MusicClass*);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA MikModSamplePlayer : public AudioTraits::PlayerClass {
|
||||
public:
|
||||
MikModSamplePlayer(void);
|
||||
virtual ~MikModSamplePlayer(void);
|
||||
|
||||
virtual void play_sample(AudioTraits::SampleClass*);
|
||||
virtual void play_music(AudioTraits::MusicClass*);
|
||||
virtual void set_volume(AudioTraits::SampleClass*, int);
|
||||
virtual void set_volume(AudioTraits::MusicClass*, int);
|
||||
public:
|
||||
// used by the readers
|
||||
static MikModSamplePlayer* get_instance(void);
|
||||
private:
|
||||
static MikModSamplePlayer* _global_instance;
|
||||
};
|
||||
|
||||
class EXPCL_PANDA MikModFmsynthPlayer : public AudioTraits::PlayerClass {
|
||||
public:
|
||||
MikModFmsynthPlayer(void);
|
||||
virtual ~MikModFmsynthPlayer(void);
|
||||
|
||||
virtual void play_sample(AudioTraits::SampleClass*);
|
||||
virtual void play_music(AudioTraits::MusicClass*);
|
||||
virtual void set_volume(AudioTraits::SampleClass*, int);
|
||||
virtual void set_volume(AudioTraits::MusicClass*, int);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA MikModMidiPlayer : public AudioTraits::PlayerClass {
|
||||
public:
|
||||
MikModMidiPlayer(void);
|
||||
virtual ~MikModMidiPlayer(void);
|
||||
|
||||
virtual void play_sample(AudioTraits::SampleClass*);
|
||||
virtual void play_music(AudioTraits::MusicClass*);
|
||||
virtual void set_volume(AudioTraits::SampleClass*, int);
|
||||
virtual void set_volume(AudioTraits::MusicClass*, int);
|
||||
public:
|
||||
// used by the readers
|
||||
static MikModMidiPlayer* get_instance(void);
|
||||
private:
|
||||
static MikModMidiPlayer* _global_instance;
|
||||
};
|
||||
|
||||
#endif /* __AUDIO_MIKMOD_TRAITS_H__ */
|
||||
67
panda/src/audio/audio_music.I
Normal file
67
panda/src/audio/audio_music.I
Normal file
@@ -0,0 +1,67 @@
|
||||
// Filename: audio_music.I
|
||||
// Created by: cary (26Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::constructor
|
||||
// Access: Protected
|
||||
// Description: initialize a new music
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioMusic::AudioMusic(AudioTraits::MusicClass* music,
|
||||
AudioTraits::PlayerClass* player,
|
||||
AudioTraits::DeleteMusicFunc* destroy,
|
||||
const string& filename) : Namable(filename),
|
||||
_music(music),
|
||||
_player(player),
|
||||
_destroy(destroy) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::copy constructor
|
||||
// Access: Protected
|
||||
// Description: copy a music, but we don't really want to allow this
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioMusic::AudioMusic(const AudioMusic& c) : Namable(c.get_name()),
|
||||
_music(c._music),
|
||||
_player(c._player),
|
||||
_destroy(c._destroy) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::assignment operator
|
||||
// Access: Protected
|
||||
// Description: copy a music, but we don't really want to allow this
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioMusic& AudioMusic::operator=(const AudioMusic& c) {
|
||||
this->set_name(c.get_name());
|
||||
this->_music = c._music;
|
||||
this->_player = c._player;
|
||||
this->_destroy = c._destroy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::get_player
|
||||
// Access: Protected
|
||||
// Description: return the player for this music
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioTraits::PlayerClass* AudioMusic::get_player(void) {
|
||||
return _player;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::get_music
|
||||
// Access: Protected
|
||||
// Description: return the trait music class for this music
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioTraits::MusicClass* AudioMusic::get_music(void) {
|
||||
return _music;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::equality operator
|
||||
// Access: Public
|
||||
// Description: test to see if two musics are the same
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AudioMusic::operator==(const AudioMusic& c) const {
|
||||
return (_music == c._music);
|
||||
}
|
||||
36
panda/src/audio/audio_music.cxx
Normal file
36
panda/src/audio/audio_music.cxx
Normal file
@@ -0,0 +1,36 @@
|
||||
// Filename: audio_music.cxx
|
||||
// Created by: cary (26Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_music.h"
|
||||
#include "config_audio.h"
|
||||
|
||||
TypeHandle AudioMusic::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::destructor
|
||||
// Access: Public
|
||||
// Description: deletes the music data and then lets the system
|
||||
// destroy this structure
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioMusic::~AudioMusic(void) {
|
||||
(*_destroy)(_music);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioMusic::status
|
||||
// Access: Public
|
||||
// Description: return the current play status of this music
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioMusic::MusicStatus AudioMusic::status(void) {
|
||||
AudioTraits::MusicClass::MusicStatus stat = _music->status();
|
||||
switch (stat) {
|
||||
case AudioTraits::MusicClass::READY:
|
||||
return READY;
|
||||
case AudioTraits::MusicClass::PLAYING:
|
||||
return PLAYING;
|
||||
}
|
||||
audio_cat->error() << "unknown status for music" << endl;
|
||||
return READY;
|
||||
}
|
||||
62
panda/src/audio/audio_music.h
Normal file
62
panda/src/audio/audio_music.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// Filename: audio_music.h
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_MUSIC_H__
|
||||
#define __AUDIO_MUSIC_H__
|
||||
|
||||
#include "audio_trait.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "namable.h"
|
||||
|
||||
class AudioPool;
|
||||
class AudioManager;
|
||||
|
||||
class EXPCL_PANDA AudioMusic : public TypedReferenceCount, public Namable {
|
||||
private:
|
||||
AudioTraits::MusicClass *_music;
|
||||
AudioTraits::PlayerClass *_player;
|
||||
AudioTraits::DeleteMusicFunc *_destroy;
|
||||
protected:
|
||||
INLINE AudioMusic(AudioTraits::MusicClass*, AudioTraits::PlayerClass*,
|
||||
AudioTraits::DeleteMusicFunc*, const string&);
|
||||
INLINE AudioMusic(const AudioMusic&);
|
||||
INLINE AudioMusic& operator=(const AudioMusic&);
|
||||
|
||||
INLINE AudioTraits::PlayerClass* get_player(void);
|
||||
INLINE AudioTraits::MusicClass* get_music(void);
|
||||
|
||||
friend class AudioPool;
|
||||
friend class AudioManager;
|
||||
public:
|
||||
virtual ~AudioMusic(void);
|
||||
INLINE bool operator==(const AudioMusic&) const;
|
||||
|
||||
enum MusicStatus { READY, PLAYING };
|
||||
|
||||
MusicStatus status(void);
|
||||
public:
|
||||
// type stuff
|
||||
static TypeHandle get_class_type(void) {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type(void) {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "AudioMusic",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type(void) const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type(void) {
|
||||
init_type();
|
||||
return get_class_type();
|
||||
}
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "audio_music.I"
|
||||
|
||||
#endif /* __AUDIO_MUSIC_H__ */
|
||||
13
panda/src/audio/audio_null_traits.I
Normal file
13
panda/src/audio/audio_null_traits.I
Normal file
@@ -0,0 +1,13 @@
|
||||
// Filename: audio_null_traits.I
|
||||
// Created by: cary (25Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
INLINE NullSample::NullSample(void) {
|
||||
}
|
||||
|
||||
INLINE NullMusic::NullMusic(void) {
|
||||
}
|
||||
|
||||
INLINE NullPlayer::NullPlayer(void) {
|
||||
}
|
||||
70
panda/src/audio/audio_null_traits.cxx
Normal file
70
panda/src/audio/audio_null_traits.cxx
Normal file
@@ -0,0 +1,70 @@
|
||||
// Filename: audio_null_traits.cxx
|
||||
// Created by: cary (25Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_null_traits.h"
|
||||
#include "audio_manager.h"
|
||||
#include "config_audio.h"
|
||||
|
||||
static bool have_initialized = false;
|
||||
|
||||
static void update_null(void) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "Update in Null audio driver" << endl;
|
||||
}
|
||||
|
||||
static void initialize(void) {
|
||||
if (have_initialized)
|
||||
return;
|
||||
AudioManager::set_update_func(update_null);
|
||||
have_initialized = true;
|
||||
}
|
||||
|
||||
NullSample::~NullSample(void) {
|
||||
}
|
||||
|
||||
float NullSample::length(void) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in sample length in Null audio driver" << endl;
|
||||
return 0.;
|
||||
}
|
||||
|
||||
AudioTraits::SampleClass::SampleStatus NullSample::status(void) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in sample status in Null audio driver" << endl;
|
||||
return AudioTraits::SampleClass::READY;
|
||||
}
|
||||
|
||||
NullMusic::~NullMusic(void) {
|
||||
}
|
||||
|
||||
AudioTraits::MusicClass::MusicStatus NullMusic::status(void) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in music status in Null audio driver" << endl;
|
||||
return READY;
|
||||
}
|
||||
|
||||
NullPlayer::~NullPlayer(void) {
|
||||
}
|
||||
|
||||
void NullPlayer::play_sample(AudioTraits::SampleClass*) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in play sample in Null audio driver" << endl;
|
||||
}
|
||||
|
||||
void NullPlayer::play_music(AudioTraits::MusicClass*) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in play music in Null audio driver" << endl;
|
||||
}
|
||||
|
||||
void NullPlayer::set_volume(AudioTraits::SampleClass*, int) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in set volume (sample) in Null audio driver"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void NullPlayer::set_volume(AudioTraits::MusicClass*, int) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in set volume (music) in Null audio driver" << endl;
|
||||
}
|
||||
41
panda/src/audio/audio_null_traits.h
Normal file
41
panda/src/audio/audio_null_traits.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// Filename: audio_null_traits.h
|
||||
// Created by: cary (25Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_NULL_TRAITS_H__
|
||||
#define __AUDIO_NULL_TRAITS_H__
|
||||
|
||||
#include "audio_trait.h"
|
||||
|
||||
class EXPCL_PANDA NullSample : public AudioTraits::SampleClass {
|
||||
public:
|
||||
INLINE NullSample(void);
|
||||
virtual ~NullSample(void);
|
||||
|
||||
virtual float length(void);
|
||||
virtual AudioTraits::SampleClass::SampleStatus status(void);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA NullMusic : public AudioTraits::MusicClass {
|
||||
public:
|
||||
INLINE NullMusic(void);
|
||||
virtual ~NullMusic(void);
|
||||
|
||||
virtual AudioTraits::MusicClass::MusicStatus status(void);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA NullPlayer : public AudioTraits::PlayerClass {
|
||||
public:
|
||||
INLINE NullPlayer(void);
|
||||
virtual ~NullPlayer(void);
|
||||
|
||||
virtual void play_sample(AudioTraits::SampleClass*);
|
||||
virtual void play_music(AudioTraits::MusicClass*);
|
||||
virtual void set_volume(AudioTraits::SampleClass*, int);
|
||||
virtual void set_volume(AudioTraits::MusicClass*, int);
|
||||
};
|
||||
|
||||
#include "audio_null_traits.I"
|
||||
|
||||
#endif /* __AUDIO_NULL_TRAITS_H__ */
|
||||
141
panda/src/audio/audio_pool.I
Normal file
141
panda/src/audio/audio_pool.I
Normal file
@@ -0,0 +1,141 @@
|
||||
// Filename: audio_pool.I
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::has_sample
|
||||
// Access: Public, Static
|
||||
// Description: Returns true if the sample has ever been loaded,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AudioPool::has_sample(const string& filename) {
|
||||
return get_ptr()->ns_has_sample(filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::verify_sample
|
||||
// Access: Public, Static
|
||||
// Description: Loads the given filename up into a sample, if it has
|
||||
// not already been loaded, and returns true to indicate
|
||||
// success, or false to indicate failure. If this
|
||||
// returns true, it is guaranteed that a subsequent call
|
||||
// to load_sample() with the same sample name will
|
||||
// return a valid AudioSample pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AudioPool::verify_sample(const string& filename) {
|
||||
return load_sample(filename) != (AudioSample*)0L;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::load_sample
|
||||
// Access: Public, Static
|
||||
// Description: Loads the given filename up into a sample, if it has
|
||||
// not already been loaded, and returns the new sample.
|
||||
// If a sample with the same filename was previously
|
||||
// loaded, returns that one instead. If the sample
|
||||
// file cannot be found, returns NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioSample* AudioPool::load_sample(const string& filename) {
|
||||
return get_ptr()->ns_load_sample(filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::release_sample
|
||||
// Access: Public, Static
|
||||
// Description: Removes the indicated sample from the pool,
|
||||
// indicating it will never be loaded again; the sample
|
||||
// may then be freed. If this function is never called,
|
||||
// a reference count will be maintained on every sample
|
||||
// ever loaded, and samples will never be freed.
|
||||
//
|
||||
// The sample's name should not have been changed
|
||||
// during its lifetime, or this function may fail to
|
||||
// locate it in the pool.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioPool::release_sample(AudioSample* sample) {
|
||||
get_ptr()->ns_release_sample(sample);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::release_all_samples
|
||||
// Access: Public, Static
|
||||
// Description: Releases all samples in the pool and restores the
|
||||
// pool to the empty state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioPool::release_all_samples(void) {
|
||||
get_ptr()->ns_release_all_samples();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::has_music
|
||||
// Access: Public, Static
|
||||
// Description: Returns true if the music has ever been loaded,
|
||||
// false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AudioPool::has_music(const string& filename) {
|
||||
return get_ptr()->ns_has_music(filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::verify_music
|
||||
// Access: Public, Static
|
||||
// Description: Loads the given filename up into a music, if it has
|
||||
// not already been loaded, and returns true to indicate
|
||||
// success, or false to indicate failure. If this
|
||||
// returns true, it is guaranteed that a subsequent call
|
||||
// to load_music() with the same music name will
|
||||
// return a valid AudioMusic pointer.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AudioPool::verify_music(const string& filename) {
|
||||
return load_music(filename) != (AudioMusic*)0L;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::load_music
|
||||
// Access: Public, Static
|
||||
// Description: Loads the given filename up into a music, if it has
|
||||
// not already been loaded, and returns the new music.
|
||||
// If a music with the same filename was previously
|
||||
// loaded, returns that one instead. If the music
|
||||
// file cannot be found, returns NULL.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioMusic* AudioPool::load_music(const string& filename) {
|
||||
return get_ptr()->ns_load_music(filename);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::release_music
|
||||
// Access: Public, Static
|
||||
// Description: Removes the indicated music from the pool,
|
||||
// indicating it will never be loaded again; the music
|
||||
// may then be freed. If this function is never called,
|
||||
// a reference count will be maintained on every music
|
||||
// ever loaded, and music will never be freed.
|
||||
//
|
||||
// The music's name should not have been changed
|
||||
// during its lifetime, or this function may fail to
|
||||
// locate it in the pool.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioPool::release_music(AudioMusic* music) {
|
||||
get_ptr()->ns_release_music(music);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::release_all_music
|
||||
// Access: Public, Static
|
||||
// Description: Releases all music in the pool and restores the
|
||||
// pool to the empty state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void AudioPool::release_all_music(void) {
|
||||
get_ptr()->ns_release_all_music();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::Constructor
|
||||
// Access: Private
|
||||
// Description: The constructor is not intended to be called
|
||||
// directly; there's only supposed to be one AudioPool
|
||||
// in the universe and it constructs itself.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioPool::AudioPool(void) {}
|
||||
243
panda/src/audio/audio_pool.cxx
Normal file
243
panda/src/audio/audio_pool.cxx
Normal file
@@ -0,0 +1,243 @@
|
||||
// Filename: audio_pool.cxx
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_pool.h"
|
||||
#include "config_audio.h"
|
||||
#include <config_util.h>
|
||||
|
||||
AudioPool* AudioPool::_global_ptr = (AudioPool*)0L;
|
||||
typedef map<string, AudioPool::SampleLoadFunc*> SampleLoaders;
|
||||
SampleLoaders* _sample_loaders = (SampleLoaders*)0L;
|
||||
typedef map<string, AudioPool::MusicLoadFunc*> MusicLoaders;
|
||||
MusicLoaders* _music_loaders = (MusicLoaders*)0L;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: check_sample_loaders
|
||||
// Access: Static
|
||||
// Description: ensure that the sample loaders map has been initialized
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static void check_sample_loaders(void) {
|
||||
if (_sample_loaders == (SampleLoaders*)0L)
|
||||
_sample_loaders = new SampleLoaders;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: check_music_loaders
|
||||
// Access: Static
|
||||
// Description: ensure that the music loaders map has been initialized
|
||||
////////////////////////////////////////////////////////////////////
|
||||
static void check_music_loaders(void) {
|
||||
if (_music_loaders == (MusicLoaders*)0L)
|
||||
_music_loaders = new MusicLoaders;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::get_ptr
|
||||
// Access: Private, Static
|
||||
// Description: Initializes and/or returns the global pointer to the
|
||||
// one AudioPool object in the system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioPool* AudioPool::get_ptr(void) {
|
||||
if (_global_ptr == (AudioPool*)0L)
|
||||
_global_ptr = new AudioPool;
|
||||
return _global_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_has_sample
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of has_sample().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AudioPool::ns_has_sample(Filename filename) {
|
||||
filename.resolve_filename(get_sound_path());
|
||||
|
||||
SampleMap::const_iterator si;
|
||||
si = _samples.find(filename);
|
||||
if (si != _samples.end()) {
|
||||
// this sample was previously loaded
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_load_sample
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of load_sample().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioSample* AudioPool::ns_load_sample(Filename filename) {
|
||||
filename.resolve_filename(get_sound_path());
|
||||
|
||||
SampleMap::const_iterator si;
|
||||
si = _samples.find(filename);
|
||||
if (si != _samples.end()) {
|
||||
// this sample was previously loaded
|
||||
return (*si).second;
|
||||
}
|
||||
audio_cat.info() << "Loading sample " << filename << "\n";
|
||||
AudioTraits::SampleClass* sample = (AudioTraits::SampleClass*)0L;
|
||||
AudioTraits::PlayerClass* player = (AudioTraits::PlayerClass*)0L;
|
||||
AudioTraits::DeleteSampleFunc* destroy = (AudioTraits::DeleteSampleFunc*)0L;
|
||||
string ext = filename.get_extension();
|
||||
SampleLoaders::const_iterator sli;
|
||||
check_sample_loaders();
|
||||
sli = _sample_loaders->find(ext);
|
||||
if (sli == _sample_loaders->end()) {
|
||||
audio_cat->error() << "no loader available for audio type '" << ext
|
||||
<< "'" << endl;
|
||||
return (AudioSample*)0L;
|
||||
}
|
||||
(*((*sli).second))(&sample, &player, &destroy, filename);
|
||||
if ((sample == (AudioTraits::SampleClass*)0L) ||
|
||||
(player == (AudioTraits::PlayerClass*)0L) ||
|
||||
(destroy == (AudioTraits::DeleteSampleFunc*)0L)) {
|
||||
audio_cat->error() << "could not load '" << filename << "'" << endl;
|
||||
return (AudioSample*)0L;
|
||||
}
|
||||
PT(AudioSample) the_sample = new AudioSample(sample, player, destroy,
|
||||
filename);
|
||||
_samples[filename] = the_sample;
|
||||
return the_sample;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_release_sample
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of release_sample().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioPool::ns_release_sample(AudioSample* sample) {
|
||||
string filename = sample->get_name();
|
||||
SampleMap::iterator si;
|
||||
si = _samples.find(filename);
|
||||
if (si != _samples.end() && (*si).second == sample) {
|
||||
_samples.erase(si);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_release_all_samples
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of release_all_samples().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioPool::ns_release_all_samples(void) {
|
||||
_samples.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::register_sample_loader
|
||||
// Access: Public, static
|
||||
// Description: A static function to register a function for loading
|
||||
// audio samples.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioPool::register_sample_loader(const string& ext,
|
||||
AudioPool::SampleLoadFunc* func) {
|
||||
SampleLoaders::const_iterator sli;
|
||||
check_sample_loaders();
|
||||
sli = _sample_loaders->find(ext);
|
||||
if (sli != _sample_loaders->end()) {
|
||||
audio_cat->warning() << "attempted to register a loader for audio type '"
|
||||
<< ext << "' more then once." << endl;
|
||||
return;
|
||||
}
|
||||
(*_sample_loaders)[ext] = func;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_has_music
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of has_music().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool AudioPool::ns_has_music(Filename filename) {
|
||||
filename.resolve_filename(get_sound_path());
|
||||
|
||||
MusicMap::const_iterator si;
|
||||
si = _music.find(filename);
|
||||
if (si != _music.end()) {
|
||||
// this music was previously loaded
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_load_music
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of load_music().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioMusic* AudioPool::ns_load_music(Filename filename) {
|
||||
filename.resolve_filename(get_sound_path());
|
||||
|
||||
MusicMap::const_iterator si;
|
||||
si = _music.find(filename);
|
||||
if (si != _music.end()) {
|
||||
// this sample was previously loaded
|
||||
return (*si).second;
|
||||
}
|
||||
audio_cat.info() << "Loading music " << filename << "\n";
|
||||
AudioTraits::MusicClass* music = (AudioTraits::MusicClass*)0L;
|
||||
AudioTraits::PlayerClass* player = (AudioTraits::PlayerClass*)0L;
|
||||
AudioTraits::DeleteMusicFunc* destroy = (AudioTraits::DeleteMusicFunc*)0L;
|
||||
string ext = filename.get_extension();
|
||||
MusicLoaders::const_iterator sli;
|
||||
check_music_loaders();
|
||||
sli = _music_loaders->find(ext);
|
||||
if (sli == _music_loaders->end()) {
|
||||
audio_cat->error() << "no loader available for audio type '" << ext
|
||||
<< "'" << endl;
|
||||
return (AudioMusic*)0L;
|
||||
}
|
||||
(*((*sli).second))(&music, &player, &destroy, filename);
|
||||
if ((music == (AudioTraits::MusicClass*)0L) ||
|
||||
(player == (AudioTraits::PlayerClass*)0L) ||
|
||||
(destroy == (AudioTraits::DeleteMusicFunc*)0L)) {
|
||||
audio_cat->error() << "could not load '" << filename << "'" << endl;
|
||||
return (AudioMusic*)0L;
|
||||
}
|
||||
PT(AudioMusic) the_music = new AudioMusic(music, player, destroy, filename);
|
||||
_music[filename] = the_music;
|
||||
return the_music;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_release_music
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of release_music().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioPool::ns_release_music(AudioMusic* music) {
|
||||
string filename = music->get_name();
|
||||
MusicMap::iterator si;
|
||||
si = _music.find(filename);
|
||||
if (si != _music.end() && (*si).second == music) {
|
||||
_music.erase(si);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::ns_release_all_music
|
||||
// Access: Private
|
||||
// Description: The nonstatic implementation of release_all_music().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioPool::ns_release_all_music(void) {
|
||||
_music.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioPool::register_music_loader
|
||||
// Access: Public, static
|
||||
// Description: A static function to register a function for loading
|
||||
// audio music.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioPool::register_music_loader(const string& ext,
|
||||
AudioPool::MusicLoadFunc* func) {
|
||||
MusicLoaders::const_iterator sli;
|
||||
check_music_loaders();
|
||||
sli = _music_loaders->find(ext);
|
||||
if (sli != _music_loaders->end()) {
|
||||
audio_cat->warning() << "attempted to register a loader for audio type '"
|
||||
<< ext << "' more then once." << endl;
|
||||
return;
|
||||
}
|
||||
(*_music_loaders)[ext] = func;
|
||||
}
|
||||
63
panda/src/audio/audio_pool.h
Normal file
63
panda/src/audio/audio_pool.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Filename: audio_pool.h
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_POOL_H__
|
||||
#define __AUDIO_POOL_H__
|
||||
|
||||
#include "audio_sample.h"
|
||||
#include "audio_music.h"
|
||||
#include <map>
|
||||
#include <pandabase.h>
|
||||
#include <filename.h>
|
||||
#include <pointerTo.h>
|
||||
|
||||
class EXPCL_PANDA AudioPool {
|
||||
private:
|
||||
INLINE AudioPool(void);
|
||||
|
||||
bool ns_has_sample(Filename filename);
|
||||
AudioSample* ns_load_sample(Filename filename);
|
||||
void ns_release_sample(AudioSample* sample);
|
||||
void ns_release_all_samples(void);
|
||||
|
||||
bool ns_has_music(Filename filename);
|
||||
AudioMusic* ns_load_music(Filename filename);
|
||||
void ns_release_music(AudioMusic* music);
|
||||
void ns_release_all_music(void);
|
||||
|
||||
static AudioPool* get_ptr(void);
|
||||
|
||||
static AudioPool *_global_ptr;
|
||||
typedef map<string, PT(AudioSample) > SampleMap;
|
||||
SampleMap _samples;
|
||||
typedef map<string, PT(AudioMusic) > MusicMap;
|
||||
MusicMap _music;
|
||||
public:
|
||||
typedef void SampleLoadFunc(AudioTraits::SampleClass**,
|
||||
AudioTraits::PlayerClass**,
|
||||
AudioTraits::DeleteSampleFunc**, Filename);
|
||||
|
||||
INLINE static bool has_sample(const string& filename);
|
||||
INLINE static bool verify_sample(const string& filename);
|
||||
INLINE static AudioSample* load_sample(const string& filename);
|
||||
INLINE static void release_sample(AudioSample* sample);
|
||||
INLINE static void release_all_samples(void);
|
||||
static void register_sample_loader(const string&, SampleLoadFunc*);
|
||||
|
||||
typedef void MusicLoadFunc(AudioTraits::MusicClass**,
|
||||
AudioTraits::PlayerClass**,
|
||||
AudioTraits::DeleteMusicFunc**, Filename);
|
||||
|
||||
INLINE static bool has_music(const string& filename);
|
||||
INLINE static bool verify_music(const string& filename);
|
||||
INLINE static AudioMusic* load_music(const string& filename);
|
||||
INLINE static void release_music(AudioMusic* music);
|
||||
INLINE static void release_all_music(void);
|
||||
static void register_music_loader(const string&, MusicLoadFunc*);
|
||||
};
|
||||
|
||||
#include "audio_pool.I"
|
||||
|
||||
#endif /* __AUDIO_POOL_H__ */
|
||||
67
panda/src/audio/audio_sample.I
Normal file
67
panda/src/audio/audio_sample.I
Normal file
@@ -0,0 +1,67 @@
|
||||
// Filename: audio_sample.I
|
||||
// Created by: cary (23Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::constructor
|
||||
// Access: Protected
|
||||
// Description: initialize a new sample
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioSample::AudioSample(AudioTraits::SampleClass* sample,
|
||||
AudioTraits::PlayerClass* player,
|
||||
AudioTraits::DeleteSampleFunc* destroy,
|
||||
const string& filename) : Namable(filename),
|
||||
_sample(sample),
|
||||
_player(player),
|
||||
_destroy(destroy) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::copy constructor
|
||||
// Access: Protected
|
||||
// Description: copy a sample, but we don't really want to allow this
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioSample::AudioSample(const AudioSample& c) : Namable(c.get_name()),
|
||||
_sample(c._sample),
|
||||
_player(c._player),
|
||||
_destroy(c._destroy) {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::assignment operator
|
||||
// Access: Protected
|
||||
// Description: copy a sample, but we don't really want to allow this
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioSample& AudioSample::operator=(const AudioSample& c) {
|
||||
this->set_name(c.get_name());
|
||||
this->_sample = c._sample;
|
||||
this->_player = c._player;
|
||||
this->_destroy = c._destroy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::get_player
|
||||
// Access: Protected
|
||||
// Description: return the player for this sample
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioTraits::PlayerClass* AudioSample::get_player(void) {
|
||||
return _player;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::get_sample
|
||||
// Access: Protected
|
||||
// Description: return the trait sample class for this sample
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE AudioTraits::SampleClass* AudioSample::get_sample(void) {
|
||||
return _sample;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::equality operator
|
||||
// Access: Public
|
||||
// Description: test to see if two samples are the same
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool AudioSample::operator==(const AudioSample& c) const {
|
||||
return (_sample == c._sample);
|
||||
}
|
||||
45
panda/src/audio/audio_sample.cxx
Normal file
45
panda/src/audio/audio_sample.cxx
Normal file
@@ -0,0 +1,45 @@
|
||||
// Filename: audio_sample.cxx
|
||||
// Created by: cary (23Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_sample.h"
|
||||
#include "config_audio.h"
|
||||
|
||||
TypeHandle AudioSample::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::destructor
|
||||
// Access: Public
|
||||
// Description: deletes the sample data and then lets the system
|
||||
// destroy this structure
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioSample::~AudioSample(void) {
|
||||
(*_destroy)(_sample);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::length
|
||||
// Access: Public
|
||||
// Description: return the length (in seconds) of the sample
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float AudioSample::length(void) {
|
||||
return _sample->length();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSample::status
|
||||
// Access: Public
|
||||
// Description: return the current play status of this sample
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioSample::SampleStatus AudioSample::status(void) {
|
||||
AudioTraits::SampleClass::SampleStatus stat = _sample->status();
|
||||
switch (stat) {
|
||||
case AudioTraits::SampleClass::READY:
|
||||
return READY;
|
||||
case AudioTraits::SampleClass::PLAYING:
|
||||
return PLAYING;
|
||||
}
|
||||
audio_cat->error() << "unknown status for sample" << endl;
|
||||
return READY;
|
||||
}
|
||||
63
panda/src/audio/audio_sample.h
Normal file
63
panda/src/audio/audio_sample.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Filename: audio_sample.h
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_SAMPLE_H__
|
||||
#define __AUDIO_SAMPLE_H__
|
||||
|
||||
#include "audio_trait.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "namable.h"
|
||||
|
||||
class AudioPool;
|
||||
class AudioManager;
|
||||
|
||||
class EXPCL_PANDA AudioSample : public TypedReferenceCount, public Namable {
|
||||
private:
|
||||
AudioTraits::SampleClass *_sample;
|
||||
AudioTraits::PlayerClass *_player;
|
||||
AudioTraits::DeleteSampleFunc *_destroy;
|
||||
protected:
|
||||
INLINE AudioSample(AudioTraits::SampleClass*, AudioTraits::PlayerClass*,
|
||||
AudioTraits::DeleteSampleFunc*, const string&);
|
||||
INLINE AudioSample(const AudioSample&);
|
||||
INLINE AudioSample& operator=(const AudioSample&);
|
||||
|
||||
INLINE AudioTraits::PlayerClass* get_player(void);
|
||||
INLINE AudioTraits::SampleClass* get_sample(void);
|
||||
|
||||
friend class AudioPool;
|
||||
friend class AudioManager;
|
||||
public:
|
||||
virtual ~AudioSample(void);
|
||||
INLINE bool operator==(const AudioSample&) const;
|
||||
|
||||
enum SampleStatus { READY, PLAYING } ;
|
||||
|
||||
float length(void);
|
||||
SampleStatus status(void);
|
||||
public:
|
||||
// type stuff
|
||||
static TypeHandle get_class_type(void) {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type(void) {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "AudioSample",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type(void) const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type(void) {
|
||||
init_type();
|
||||
return get_class_type();
|
||||
}
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "audio_sample.I"
|
||||
|
||||
#endif /* __AUDIO_SAMPLE_H__ */
|
||||
48
panda/src/audio/audio_trait.cxx
Normal file
48
panda/src/audio/audio_trait.cxx
Normal file
@@ -0,0 +1,48 @@
|
||||
// Filename: audio_trait.cxx
|
||||
// Created by: cary (23Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_trait.h"
|
||||
#include "config_audio.h"
|
||||
|
||||
AudioTraits::SampleClass::~SampleClass(void) {
|
||||
}
|
||||
|
||||
float AudioTraits::SampleClass::length(void) {
|
||||
audio_cat->error() << "In abstract SampleClass::length!" << endl;
|
||||
return 0.;
|
||||
}
|
||||
|
||||
AudioTraits::SampleClass::SampleStatus AudioTraits::SampleClass::status(void) {
|
||||
audio_cat->error() << "In abstract SampleClass::status!" << endl;
|
||||
return READY;
|
||||
}
|
||||
|
||||
AudioTraits::MusicClass::~MusicClass(void) {
|
||||
}
|
||||
|
||||
AudioTraits::MusicClass::MusicStatus AudioTraits::MusicClass::status(void) {
|
||||
audio_cat->error() << "In abstract MusicClass::status!" << endl;
|
||||
return READY;
|
||||
}
|
||||
|
||||
AudioTraits::PlayerClass::~PlayerClass(void) {
|
||||
}
|
||||
|
||||
void AudioTraits::PlayerClass::play_sample(AudioTraits::SampleClass*) {
|
||||
audio_cat->error() << "In abstract PlayerClass::play_sample!" << endl;
|
||||
}
|
||||
|
||||
void AudioTraits::PlayerClass::play_music(AudioTraits::MusicClass*) {
|
||||
audio_cat->error() << "In abstract PlayerClass::play_music!" << endl;
|
||||
}
|
||||
|
||||
void AudioTraits::PlayerClass::set_volume(AudioTraits::SampleClass*, int) {
|
||||
audio_cat->error() << "In abstract PlayerClass::set_volume (sample)!"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void AudioTraits::PlayerClass::set_volume(AudioTraits::MusicClass*, int) {
|
||||
audio_cat->error() << "In abstract PlayerClass::set_volume (music)!" << endl;
|
||||
}
|
||||
49
panda/src/audio/audio_trait.h
Normal file
49
panda/src/audio/audio_trait.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Filename: audio_trait.h
|
||||
// Created by: frang (06Jul00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_TRAIT_H__
|
||||
#define __AUDIO_TRAIT_H__
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
class EXPCL_PANDA AudioTraits {
|
||||
public:
|
||||
class SampleClass;
|
||||
class MusicClass;
|
||||
|
||||
typedef void DeleteSampleFunc(SampleClass*);
|
||||
typedef void DeleteMusicFunc(MusicClass*);
|
||||
|
||||
class EXPCL_PANDA SampleClass {
|
||||
public:
|
||||
SampleClass(void) {}
|
||||
virtual ~SampleClass(void);
|
||||
|
||||
enum SampleStatus { READY, PLAYING } ;
|
||||
|
||||
virtual float length(void) = 0;
|
||||
virtual SampleStatus status(void) = 0;
|
||||
};
|
||||
class EXPCL_PANDA MusicClass {
|
||||
public:
|
||||
MusicClass(void) {}
|
||||
virtual ~MusicClass(void);
|
||||
|
||||
enum MusicStatus { READY, PLAYING };
|
||||
virtual MusicStatus status(void) = 0;
|
||||
};
|
||||
class EXPCL_PANDA PlayerClass {
|
||||
public:
|
||||
PlayerClass(void) {}
|
||||
virtual ~PlayerClass(void);
|
||||
|
||||
virtual void play_sample(SampleClass*) = 0;
|
||||
virtual void play_music(MusicClass*) = 0;
|
||||
virtual void set_volume(SampleClass*, int) = 0;
|
||||
virtual void set_volume(MusicClass*, int) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* __AUDIO_TRAIT_H__ */
|
||||
28
panda/src/audio/audio_win_traits.I
Normal file
28
panda/src/audio/audio_win_traits.I
Normal file
@@ -0,0 +1,28 @@
|
||||
// Filename: audio_win_traits.I
|
||||
// Created by: cary (27Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
INLINE WinSample::WinSample(void) : _channel(NULL), _data(NULL), _len(0) {
|
||||
}
|
||||
|
||||
INLINE LPDIRECTSOUNDBUFFER WinSample::get_channel(void) {
|
||||
return _channel;
|
||||
}
|
||||
|
||||
INLINE WinMusic::WinMusic(void) : _performance(NULL), _music(NULL),
|
||||
_buffer(NULL), _synth(NULL), _data(NULL),
|
||||
_len(0) {
|
||||
init();
|
||||
}
|
||||
|
||||
INLINE IDirectMusicPerformance* WinMusic::get_performance(void) {
|
||||
return _performance;
|
||||
}
|
||||
|
||||
INLINE IDirectMusicSegment* WinMusic::get_music(void) {
|
||||
return _music;
|
||||
}
|
||||
|
||||
INLINE WinPlayer::WinPlayer(void) {
|
||||
}
|
||||
660
panda/src/audio/audio_win_traits.cxx
Normal file
660
panda/src/audio/audio_win_traits.cxx
Normal file
@@ -0,0 +1,660 @@
|
||||
// Filename: audio_win_traits.cxx
|
||||
// Created by: cary (27Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "audio_win_traits.h"
|
||||
#include "audio_manager.h"
|
||||
#include "config_audio.h"
|
||||
|
||||
#include <direct.h>
|
||||
|
||||
static bool have_initialized = false;
|
||||
static HWND global_hwnd;
|
||||
|
||||
// these are used by the direct sound playing stuff
|
||||
static LPDIRECTSOUNDBUFFER soundPrimaryBuffer = NULL;
|
||||
static LPDIRECTSOUND soundDirectSound = NULL;
|
||||
|
||||
// these are used by the direct music playing stuff
|
||||
static IDirectMusic* musicDirectMusic = NULL;
|
||||
static IDirectSound* musicDirectSound = NULL;
|
||||
|
||||
#define CHECK_RESULT(_result, _msg) \
|
||||
if (FAILED(_result)) { \
|
||||
audio_cat->error() << _msg << " at " << __FILE__ << ":" << __LINE__ \
|
||||
<< endl; \
|
||||
return; \
|
||||
}
|
||||
|
||||
// #define MULTI_TO_WIDE(_in, _out) MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, _in, -1, _out, DMUS_MAX_FILENAME)
|
||||
#define MULTI_TO_WIDE(x,y) MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, y, -1, x, _MAX_PATH);
|
||||
|
||||
static void update_win(void) {
|
||||
}
|
||||
|
||||
static void initialize(void) {
|
||||
if (have_initialized)
|
||||
return;
|
||||
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in winAudio initialize" << endl;
|
||||
|
||||
// rumor has it this will work, if it doesn't we need to create an invisible
|
||||
// application window for this kind of thing
|
||||
global_hwnd = GetDesktopWindow();
|
||||
|
||||
// initialize COM
|
||||
HRESULT result = CoInitialize(NULL);
|
||||
CHECK_RESULT(result, "CoInitialize failed");
|
||||
|
||||
//
|
||||
// initialize the globals for the direct sound drivers
|
||||
//
|
||||
|
||||
// create a direct sound object
|
||||
result = DirectSoundCreate(NULL, &soundDirectSound, NULL);
|
||||
CHECK_RESULT(result, "could not create a Direct Sound (tm) object (c)");
|
||||
|
||||
// set the cooperative level
|
||||
result = soundDirectSound->SetCooperativeLevel(global_hwnd, DSSCL_PRIORITY);
|
||||
if (FAILED(result)) {
|
||||
audio_cat->warning() << "could not set Direct Sound co-op level to "
|
||||
<< "DSSCL_PRIORITY, trying DSSCL_NORMAL" << endl;
|
||||
result = soundDirectSound->SetCooperativeLevel(global_hwnd, DSSCL_NORMAL);
|
||||
CHECK_RESULT(result, "failed setting to DSSCL_NORMAL");
|
||||
}
|
||||
|
||||
// Move any unused portions of onboard sound memory to a contiguous block
|
||||
// so that the largest portion of free memory will be available.
|
||||
soundDirectSound->Compact();
|
||||
|
||||
// create the primary buffer
|
||||
DSBUFFERDESC dsbd;
|
||||
ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
|
||||
dsbd.dwSize = sizeof(DSBUFFERDESC);
|
||||
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
|
||||
result = soundDirectSound->CreateSoundBuffer(&dsbd, &soundPrimaryBuffer,
|
||||
NULL);
|
||||
CHECK_RESULT(result, "could not create primary buffer");
|
||||
|
||||
// set primary buffer format to 22kHz and 16-bit output
|
||||
// COME BACK LATER TO MAKE THIS CONFIG
|
||||
WAVEFORMATEX wfx;
|
||||
ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
|
||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wfx.nChannels = 2;
|
||||
wfx.nSamplesPerSec = 22050;
|
||||
wfx.wBitsPerSample = 16;
|
||||
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
|
||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||
result = soundPrimaryBuffer->SetFormat(&wfx);
|
||||
// SetFormat requires at least DSSCL_PRIORITY, which we may not have
|
||||
if (result == DSERR_PRIOLEVELNEEDED)
|
||||
audio_cat->warning() << "could not set format of Primary Buffer because "
|
||||
<< "we didn't get DSSCL_PRIORITY" << endl;
|
||||
|
||||
/*
|
||||
//
|
||||
// initialize the globals for the direct music drivers
|
||||
//
|
||||
|
||||
// create the direct sound object
|
||||
result = DirectSoundCreate(NULL, &musicDirectSound, NULL);
|
||||
CHECK_RESULT(result,
|
||||
"could not create a second Direct Sound (tm) object (c)");
|
||||
|
||||
// set the cooperative level
|
||||
result = musicDirectSound->SetCooperativeLevel(global_hwnd, DSSCL_PRIORITY);
|
||||
if (FAILED(result)) {
|
||||
audio_cat->warning() << "could not set Direct Sound (2) co-op level to "
|
||||
<< "DSSCL_PRIORITY, trying DSSCL_NORMAL" << endl;
|
||||
result = musicDirectSound->SetCooperativeLevel(global_hwnd, DSSCL_NORMAL);
|
||||
CHECK_RESULT(result, "failed setting to DSSCL_NORMAL");
|
||||
}
|
||||
|
||||
// create the direct music object
|
||||
result = CoCreateInstance(CLSID_DirectMusic, NULL, CLSCTX_INPROC,
|
||||
IID_IDirectMusic, (void**)&musicDirectMusic);
|
||||
CHECK_RESULT(result, "could not create Direct Music (tm) object (c)");
|
||||
|
||||
// set direct sound for direct music
|
||||
result = musicDirectMusic->SetDirectSound(musicDirectSound, NULL);
|
||||
CHECK_RESULT(result, "could not add Direct Sound (tm) to Direct Music (tm)");
|
||||
*/
|
||||
|
||||
//
|
||||
// finish out with our stuff
|
||||
//
|
||||
|
||||
AudioManager::set_update_func(update_win);
|
||||
have_initialized = true;
|
||||
}
|
||||
|
||||
static void shutdown(void) {
|
||||
// release the primary sound buffer
|
||||
if (soundPrimaryBuffer) {
|
||||
soundPrimaryBuffer->Release();
|
||||
soundPrimaryBuffer = NULL;
|
||||
}
|
||||
|
||||
// release direct sound object
|
||||
if (soundDirectSound) {
|
||||
soundDirectSound->Release();
|
||||
soundDirectSound = NULL;
|
||||
}
|
||||
|
||||
// release direct music object
|
||||
if (musicDirectMusic) {
|
||||
musicDirectMusic->Release();
|
||||
musicDirectMusic = NULL;
|
||||
}
|
||||
|
||||
if (musicDirectSound) {
|
||||
musicDirectSound->Release();
|
||||
musicDirectSound = NULL;
|
||||
}
|
||||
|
||||
// shutdown COM
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
WinSample::~WinSample(void) {
|
||||
// unload any data we have
|
||||
if (_channel) {
|
||||
_channel->Release();
|
||||
_channel = NULL;
|
||||
}
|
||||
// we may or may not be leaking the _data
|
||||
}
|
||||
|
||||
float WinSample::length(void) {
|
||||
// DO THIS
|
||||
return 0.;
|
||||
}
|
||||
|
||||
AudioTraits::SampleClass::SampleStatus WinSample::status(void) {
|
||||
if (_channel) {
|
||||
DWORD dwStatus;
|
||||
_channel->GetStatus(&dwStatus);
|
||||
if (dwStatus & DSBSTATUS_PLAYING)
|
||||
return AudioTraits::SampleClass::PLAYING;
|
||||
}
|
||||
return AudioTraits::SampleClass::READY;
|
||||
}
|
||||
|
||||
BYTE* WinSample::lock(void) {
|
||||
HRESULT result = _channel->Lock(0, 0, (void**)&_data, &_len, NULL, 0,
|
||||
DSBLOCK_ENTIREBUFFER);
|
||||
if (FAILED(result)) {
|
||||
audio_cat->error() << "failed to lock buffer" << endl;
|
||||
return NULL;
|
||||
}
|
||||
return _data;
|
||||
}
|
||||
|
||||
void WinSample::unlock(void) {
|
||||
HRESULT result = _channel->Unlock(_data, _len, NULL, 0);
|
||||
CHECK_RESULT(result, "failed to unlock buffer");
|
||||
}
|
||||
|
||||
// these are used by the wav loader
|
||||
WAVEFORMATEX* pwfx;
|
||||
HMMIO hmmioIn;
|
||||
MMCKINFO ckIn;
|
||||
MMCKINFO ckInRiff;
|
||||
|
||||
HRESULT readMMIO(HMMIO hmmio, MMCKINFO* pckInRIFF, WAVEFORMATEX** ppwfxInfo) {
|
||||
MMCKINFO ckin;
|
||||
PCMWAVEFORMAT pcmWaveFormat;
|
||||
|
||||
*ppwfxInfo = NULL;
|
||||
if (mmioDescend(hmmio, pckInRIFF, NULL, 0) != 0)
|
||||
return E_FAIL;
|
||||
if ((pckInRIFF->ckid != FOURCC_RIFF) ||
|
||||
(mmioFOURCC('W', 'A', 'V', 'E') != pckInRIFF->fccType))
|
||||
return E_FAIL;
|
||||
ckin.ckid = mmioFOURCC('f', 'm', 't', ' ');
|
||||
if (mmioDescend(hmmio, &ckin, pckInRIFF, MMIO_FINDCHUNK) != 0)
|
||||
return E_FAIL;
|
||||
if (ckin.cksize < (LONG)sizeof(PCMWAVEFORMAT))
|
||||
return E_FAIL;
|
||||
if (mmioRead(hmmio, (HPSTR)&pcmWaveFormat, sizeof(pcmWaveFormat)) !=
|
||||
sizeof(pcmWaveFormat))
|
||||
return E_FAIL;
|
||||
if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM) {
|
||||
if ((*ppwfxInfo = new WAVEFORMATEX) == NULL)
|
||||
return E_FAIL;
|
||||
memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat));
|
||||
(*ppwfxInfo)->cbSize = 0;
|
||||
} else {
|
||||
WORD cbExtraBytes = 0L;
|
||||
if (mmioRead(hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD))
|
||||
return E_FAIL;
|
||||
*ppwfxInfo = (WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX)+cbExtraBytes];
|
||||
if (*ppwfxInfo == NULL)
|
||||
return E_FAIL;
|
||||
memcpy(*ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat));
|
||||
(*ppwfxInfo)->cbSize = cbExtraBytes;
|
||||
if (mmioRead(hmmio, (CHAR*)(((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(WORD)),
|
||||
cbExtraBytes) != cbExtraBytes) {
|
||||
delete *ppwfxInfo;
|
||||
*ppwfxInfo = NULL;
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
if (mmioAscend(hmmio, &ckin, 0) != 0) {
|
||||
delete *ppwfxInfo;
|
||||
*ppwfxInfo = NULL;
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT wave_open_file(const CHAR* strFileName, HMMIO* phmmioIn,
|
||||
WAVEFORMATEX** ppwfxInfo, MMCKINFO* pckInRIFF) {
|
||||
HMMIO hmmio = NULL;
|
||||
if ((hmmio = mmioOpen(const_cast<CHAR*>(strFileName), NULL,
|
||||
MMIO_ALLOCBUF | MMIO_READ)) == NULL)
|
||||
return E_FAIL;
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = readMMIO(hmmio, pckInRIFF, ppwfxInfo))) {
|
||||
mmioClose(hmmio, 0);
|
||||
return hr;
|
||||
}
|
||||
*phmmioIn = hmmio;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT wave_start_data_read(HMMIO* phmmioIn, MMCKINFO* pckIn,
|
||||
MMCKINFO* pckInRIFF) {
|
||||
// seek to the data
|
||||
if (mmioSeek(*phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC),
|
||||
SEEK_SET) == -1)
|
||||
return E_FAIL;
|
||||
//search the input file for the 'data' chunk
|
||||
pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a');
|
||||
if (mmioDescend(*phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK) != 0)
|
||||
return E_FAIL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT wave_read_file(HMMIO hmmio, UINT cbRead, BYTE* pbDest, MMCKINFO* pckIn,
|
||||
UINT* cbActualRead) {
|
||||
MMIOINFO mmioinfoIn;
|
||||
*cbActualRead = 0;
|
||||
if (mmioGetInfo(hmmio, &mmioinfoIn, 0) != 0)
|
||||
return E_FAIL;
|
||||
UINT cbDataIn = cbRead;
|
||||
if (cbDataIn > pckIn->cksize)
|
||||
cbDataIn = pckIn->cksize;
|
||||
for (DWORD cT=0; cT<cbDataIn; ++cT) {
|
||||
// copy bytes from the io to the buffer
|
||||
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead) {
|
||||
if (mmioAdvance(hmmio, &mmioinfoIn, MMIO_READ) != 0)
|
||||
return E_FAIL;
|
||||
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
|
||||
return E_FAIL;
|
||||
}
|
||||
// actual copy
|
||||
*((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext);
|
||||
mmioinfoIn.pchNext++;
|
||||
}
|
||||
if (mmioSetInfo(hmmio, &mmioinfoIn, 0) != 0)
|
||||
return E_FAIL;
|
||||
*cbActualRead = cbDataIn;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT wave_load_internal(const CHAR* filename, WAVEFORMATEX& wavInfo,
|
||||
BYTE*& wavData, UINT& wavSize) {
|
||||
wavData = NULL;
|
||||
wavSize = 0;
|
||||
HRESULT result = wave_open_file(filename, &hmmioIn, &pwfx, &ckInRiff);
|
||||
if (FAILED(result))
|
||||
return result;
|
||||
result = wave_start_data_read(&hmmioIn, &ckIn, &ckInRiff);
|
||||
if (SUCCEEDED(result)) {
|
||||
memcpy(&wavInfo, pwfx, sizeof(WAVEFORMATEX));
|
||||
DWORD size = ckIn.cksize + ckIn.dwDataOffset;
|
||||
wavData = new BYTE[size];
|
||||
result = wave_read_file(hmmioIn, size, wavData, &ckIn, &wavSize);
|
||||
}
|
||||
mmioClose(hmmioIn, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT wave_load(const CHAR* filename, WAVEFORMATEX& wavInfo, BYTE*& wavData,
|
||||
UINT& wavSize) {
|
||||
pwfx = NULL;
|
||||
HRESULT result = wave_load_internal(filename, wavInfo, wavData, wavSize);
|
||||
if (pwfx) {
|
||||
delete pwfx;
|
||||
pwfx = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
WinSample* WinSample::load_wav(Filename filename) {
|
||||
WinSample* ret = (WinSample*)0L;
|
||||
|
||||
initialize();
|
||||
WAVEFORMATEX wavInfo;
|
||||
UINT wavSize = 0;
|
||||
BYTE* wavData = NULL;
|
||||
|
||||
HRESULT result = wave_load(filename.c_str(), wavInfo, wavData, wavSize);
|
||||
if (FAILED(result)) {
|
||||
if (wavData)
|
||||
delete [] wavData;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// create direct sound channel
|
||||
ret = new WinSample();
|
||||
DSBUFFERDESC dsbdDesc;
|
||||
ZeroMemory(&dsbdDesc, sizeof(DSBUFFERDESC));
|
||||
dsbdDesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
/*
|
||||
dsbdDesc.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_STATIC |
|
||||
DSBCAPS_GLOBALFOCUS;
|
||||
*/
|
||||
dsbdDesc.dwFlags = DSBCAPS_STATIC |
|
||||
DSBCAPS_GLOBALFOCUS;
|
||||
dsbdDesc.dwBufferBytes = wavSize;
|
||||
dsbdDesc.lpwfxFormat = &wavInfo;
|
||||
dsbdDesc.lpwfxFormat->cbSize = sizeof(wavInfo);
|
||||
result = soundDirectSound->CreateSoundBuffer(&dsbdDesc, &(ret->_channel), NULL);
|
||||
if (FAILED(result)) {
|
||||
delete ret;
|
||||
ret = (WinSample*)0L;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
BYTE* dst = NULL;
|
||||
dst = ret->lock();
|
||||
try {
|
||||
memcpy(dst, wavData, wavSize);
|
||||
}
|
||||
catch(...) {
|
||||
delete ret;
|
||||
ret = (WinSample*)0L;
|
||||
}
|
||||
if (ret)
|
||||
ret->unlock();
|
||||
}
|
||||
|
||||
if (wavData)
|
||||
delete [] wavData;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WinSample::destroy(AudioTraits::SampleClass* sample) {
|
||||
delete sample;
|
||||
}
|
||||
|
||||
WinMusic::~WinMusic(void) {
|
||||
// AudioManager::stop(this);
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in WinMusic::~WinMusic()" << endl;
|
||||
|
||||
if (_music) {
|
||||
_music->Release();
|
||||
_music = NULL;
|
||||
}
|
||||
|
||||
if (_synth) {
|
||||
_synth->Release();
|
||||
_synth = NULL;
|
||||
}
|
||||
|
||||
if (_performance) {
|
||||
_performance->Release();
|
||||
_performance = NULL;
|
||||
}
|
||||
|
||||
if (_buffer) {
|
||||
_buffer->Release();
|
||||
_buffer = NULL;
|
||||
}
|
||||
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "out of WinMusic::~WinMusic()" << endl;
|
||||
}
|
||||
|
||||
void WinMusic::init(void) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in WinMusic::init()" << endl;
|
||||
|
||||
initialize();
|
||||
// create the direct sound performance object
|
||||
HRESULT result = CoCreateInstance(CLSID_DirectMusicPerformance, NULL,
|
||||
CLSCTX_INPROC,
|
||||
IID_IDirectMusicPerformance2,
|
||||
(void**)&_performance);
|
||||
if (FAILED(result)) {
|
||||
audio_cat->error() << "could not create performance object" << endl;
|
||||
_performance = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize performance object
|
||||
// result = _performance->Init(&musicDirectMusic, NULL, NULL);
|
||||
result = _performance->Init(NULL, NULL, NULL);
|
||||
CHECK_RESULT(result, "could not initialize performance object");
|
||||
|
||||
/*
|
||||
// create the output synth object
|
||||
DMUS_PORTPARAMS params;
|
||||
ZeroMemory(¶ms, sizeof(DMUS_PORTPARAMS));
|
||||
params.dwSize = sizeof(DMUS_PORTPARAMS);
|
||||
result = musicDirectMusic->CreatePort(GUID_NULL, ¶ms, &_synth, NULL);
|
||||
CHECK_RESULT(result, "could not create synth");
|
||||
|
||||
// create sound buffer
|
||||
WAVEFORMATEX format;
|
||||
DWORD formatExSize;
|
||||
DWORD bufferSize;
|
||||
ZeroMemory(&format, sizeof(WAVEFORMATEX));
|
||||
formatExSize = format.cbSize = sizeof(WAVEFORMATEX);
|
||||
result = _synth->GetFormat(&format, &formatExSize, &bufferSize);
|
||||
CHECK_RESULT(result, "failed to get format from synth");
|
||||
DSBUFFERDESC bufferDesc;
|
||||
ZeroMemory(&bufferDesc, sizeof(DSBUFFERDESC));
|
||||
bufferDesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
*
|
||||
bufferDesc.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_STICKYFOCUS;
|
||||
*
|
||||
bufferDesc.dwFlags = DSBCAPS_STICKYFOCUS;
|
||||
bufferDesc.dwBufferBytes = bufferSize;
|
||||
bufferDesc.lpwfxFormat = &format;
|
||||
bufferDesc.lpwfxFormat->cbSize = sizeof(WAVEFORMATEX);
|
||||
result = musicDirectSound->CreateSoundBuffer(&bufferDesc, &_buffer, NULL);
|
||||
CHECK_RESULT(result, "could not create buffer for music");
|
||||
|
||||
// initialize synth
|
||||
result = _synth->SetDirectSound(musicDirectSound, _buffer);
|
||||
CHECK_RESULT(result, "failed to initialize synth");
|
||||
|
||||
// activate synth
|
||||
result = _synth->Activate(TRUE);
|
||||
CHECK_RESULT(result, "failed to activate synth");
|
||||
*/
|
||||
|
||||
// add the synth to the performance
|
||||
// result = _performance->AddPort(_synth);
|
||||
result = _performance->AddPort(NULL);
|
||||
CHECK_RESULT(result, "failed to add synth to performance");
|
||||
|
||||
/*
|
||||
// allocate performance channels
|
||||
result = _performance->AssignPChannelBlock(0, _synth, 1);
|
||||
CHECK_RESULT(result, "failed to assign performance channels");
|
||||
*/
|
||||
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "out of WinMusic::init() _performance = "
|
||||
<< (void*)_performance << " _synth = "
|
||||
<< (void*)_synth << " _buffer = " << (void*)_buffer
|
||||
<< endl;
|
||||
}
|
||||
|
||||
AudioTraits::MusicClass::MusicStatus WinMusic::status(void) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in WinMusic::status()" << endl;
|
||||
|
||||
if (_performance && _music) {
|
||||
if (_performance->IsPlaying(_music, NULL) == S_OK) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "returning PLAYING" << endl;
|
||||
return PLAYING;
|
||||
}
|
||||
} else
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "MusicStatus no performance or music!" << endl;
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "returning READY" << endl;
|
||||
return READY;
|
||||
}
|
||||
|
||||
WinMusic* WinMusic::load_midi(Filename filename) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in WinMusic::load_midi()" << endl;
|
||||
initialize();
|
||||
// WinMusic* ret = (WinMusic*)0L;
|
||||
WinMusic* ret = new WinMusic();
|
||||
if (ret->_performance && ret->_music) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "for some reason, have to stop" << endl;
|
||||
ret->_performance->Stop(NULL, NULL, 0, 0);
|
||||
}
|
||||
ret->_music = NULL;
|
||||
IDirectMusicLoader* loader;
|
||||
HRESULT result = CoCreateInstance(CLSID_DirectMusicLoader, NULL,
|
||||
CLSCTX_INPROC, IID_IDirectMusicLoader,
|
||||
(void**)&loader);
|
||||
if (FAILED(result)) {
|
||||
audio_cat->error() << "could not create music loader" << endl;
|
||||
delete ret;
|
||||
ret = (WinMusic*)0L;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char szDir[_MAX_PATH];
|
||||
WCHAR wszDir[_MAX_PATH];
|
||||
if (_getcwd(szDir, _MAX_PATH)==NULL) {
|
||||
audio_cat->error() << "could not getcwd" << endl;
|
||||
delete ret;
|
||||
ret = (WinMusic*)0L;
|
||||
return ret;
|
||||
}
|
||||
MULTI_TO_WIDE(wszDir, szDir);
|
||||
result = loader->SetSearchDirectory(GUID_DirectMusicAllTypes, wszDir, FALSE);
|
||||
if (FAILED(result)) {
|
||||
audio_cat->error() << "could not set search directory" << endl;
|
||||
delete ret;
|
||||
ret = (WinMusic*)0L;
|
||||
return ret;
|
||||
}
|
||||
|
||||
DMUS_OBJECTDESC fdesc;
|
||||
fdesc.guidClass = CLSID_DirectMusicSegment;
|
||||
fdesc.dwSize = sizeof(DMUS_OBJECTDESC);
|
||||
// MULTI_TO_WIDE(filename.c_str(), fdesc.wszFileName);
|
||||
MULTI_TO_WIDE(fdesc.wszFileName, filename.c_str());
|
||||
// fdesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME | DMUS_OBJ_FULLPATH;
|
||||
fdesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
|
||||
result = loader->GetObject(&fdesc, IID_IDirectMusicSegment2,
|
||||
(void**)&(ret->_music));
|
||||
if (FAILED(result)) {
|
||||
audio_cat->error() << "failed to load file" << endl;
|
||||
loader->Release();
|
||||
delete ret;
|
||||
ret = (WinMusic*)0L;
|
||||
return ret;
|
||||
}
|
||||
ret->_music->SetParam(GUID_StandardMIDIFile, -1, 0, 0,
|
||||
(void*)(ret->_performance));
|
||||
ret->_music->SetParam(GUID_Download, -1, 0, 0, (void*)(ret->_performance));
|
||||
// ret->_buffer->SetVolume(0);
|
||||
// ret->_buffer->SetPan(0);
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "out of WinMusic::load_midi() _music = "
|
||||
<< (void*)ret->_music << endl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void WinMusic::destroy(AudioTraits::MusicClass* music) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in WinMusic::destroy()" << endl;
|
||||
delete music;
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "out of WinMusic::destroy()" << endl;
|
||||
}
|
||||
|
||||
WinPlayer* WinPlayer::_global_instance = (WinPlayer*)0L;
|
||||
|
||||
WinPlayer::~WinPlayer(void) {
|
||||
}
|
||||
|
||||
void WinPlayer::play_sample(AudioTraits::SampleClass* sample) {
|
||||
initialize();
|
||||
WinSample* wsample = (WinSample*)sample;
|
||||
LPDIRECTSOUNDBUFFER chan = wsample->get_channel();
|
||||
if (chan) {
|
||||
chan->Stop();
|
||||
HRESULT result = chan->Play(0, 0, 0);
|
||||
if (FAILED(result))
|
||||
audio_cat->error() << "sample play failed" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void WinPlayer::play_music(AudioTraits::MusicClass* music) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "in WinPlayer::play_music()" << endl;
|
||||
initialize();
|
||||
WinMusic* wmusic = (WinMusic*)music;
|
||||
IDirectMusicPerformance* _perf = wmusic->get_performance();
|
||||
IDirectMusicSegment* _msc = wmusic->get_music();
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "about to jump in: _perf = " << (void*)_perf
|
||||
<< " _msc = " << (void*)_msc << endl;
|
||||
if (_perf && _msc) {
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "made it inside" << endl;
|
||||
// _msc->SetRepeats(0);
|
||||
IDirectMusicSegmentState* segState;
|
||||
// HRESULT result = _perf->PlaySegment(_msc, 0, 0, NULL);
|
||||
HRESULT result = _perf->PlaySegment(_msc, 0, 0, &segState);
|
||||
if (result != S_OK) {
|
||||
audio_cat->error() << "music play failed" << endl;
|
||||
switch (result) {
|
||||
case E_OUTOFMEMORY: audio_cat->error() << "reports out of memory" << endl;
|
||||
break;
|
||||
case E_POINTER: audio_cat->error() << "reports invalid pointer" << endl;
|
||||
break;
|
||||
case DMUS_E_NO_MASTER_CLOCK: audio_cat->error() << "reports no master clock" << endl;
|
||||
break;
|
||||
case DMUS_E_SEGMENT_INIT_FAILED: audio_cat->error() << "reports segment init failed" << endl;
|
||||
break;
|
||||
case DMUS_E_TIME_PAST: audio_cat->error() << "reports time past" << endl;
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
if (audio_cat->is_debug())
|
||||
audio_cat->debug() << "out of WinPlayer::play_music()" << endl;
|
||||
}
|
||||
|
||||
void WinPlayer::set_volume(AudioTraits::SampleClass*, int) {
|
||||
}
|
||||
|
||||
void WinPlayer::set_volume(AudioTraits::MusicClass*, int) {
|
||||
}
|
||||
|
||||
WinPlayer* WinPlayer::get_instance(void) {
|
||||
if (_global_instance == (WinPlayer*)0L)
|
||||
_global_instance = new WinPlayer();
|
||||
return _global_instance;
|
||||
}
|
||||
78
panda/src/audio/audio_win_traits.h
Normal file
78
panda/src/audio/audio_win_traits.h
Normal file
@@ -0,0 +1,78 @@
|
||||
// Filename: audio_win_traits.h
|
||||
// Created by: cary (27Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __AUDIO_WIN_TRAITS_H__
|
||||
#define __AUDIO_WIN_TRAITS_H__
|
||||
|
||||
#include "audio_trait.h"
|
||||
#include <filename.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <dsound.h>
|
||||
#include <dmusici.h>
|
||||
|
||||
class EXPCL_PANDA WinSample : public AudioTraits::SampleClass {
|
||||
private:
|
||||
LPDIRECTSOUNDBUFFER _channel;
|
||||
BYTE* _data;
|
||||
DWORD _len;
|
||||
public:
|
||||
INLINE WinSample(void);
|
||||
virtual ~WinSample(void);
|
||||
|
||||
virtual float length(void);
|
||||
virtual AudioTraits::SampleClass::SampleStatus status(void);
|
||||
public:
|
||||
// these are used by the laoders
|
||||
BYTE* lock(void);
|
||||
void unlock(void);
|
||||
static WinSample* load_wav(Filename);
|
||||
static void destroy(AudioTraits::SampleClass*);
|
||||
// these are used by the player
|
||||
INLINE LPDIRECTSOUNDBUFFER get_channel(void);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA WinMusic : public AudioTraits::MusicClass {
|
||||
private:
|
||||
IDirectMusicPerformance* _performance;
|
||||
IDirectMusicSegment* _music;
|
||||
IDirectSoundBuffer* _buffer;
|
||||
IDirectMusicPort* _synth;
|
||||
BYTE* _data;
|
||||
DWORD _len;
|
||||
|
||||
void init(void);
|
||||
public:
|
||||
INLINE WinMusic(void);
|
||||
virtual ~WinMusic(void);
|
||||
|
||||
virtual AudioTraits::MusicClass::MusicStatus status(void);
|
||||
// these are used by the loaders
|
||||
static WinMusic* load_midi(Filename);
|
||||
static void destroy(AudioTraits::MusicClass*);
|
||||
// these are used by the players
|
||||
INLINE IDirectMusicPerformance* get_performance(void);
|
||||
INLINE IDirectMusicSegment* get_music(void);
|
||||
};
|
||||
|
||||
class EXPCL_PANDA WinPlayer : public AudioTraits::PlayerClass {
|
||||
public:
|
||||
INLINE WinPlayer(void);
|
||||
virtual ~WinPlayer(void);
|
||||
|
||||
virtual void play_sample(AudioTraits::SampleClass*);
|
||||
virtual void play_music(AudioTraits::MusicClass*);
|
||||
virtual void set_volume(AudioTraits::SampleClass*, int);
|
||||
virtual void set_volume(AudioTraits::MusicClass*, int);
|
||||
public:
|
||||
// used by the readers
|
||||
static WinPlayer* get_instance(void);
|
||||
private:
|
||||
static WinPlayer* _global_instance;
|
||||
};
|
||||
|
||||
#include "audio_win_traits.I"
|
||||
|
||||
#endif /* __AUDIO_WIN_TRAITS_H__ */
|
||||
41
panda/src/audio/config_audio.cxx
Normal file
41
panda/src/audio/config_audio.cxx
Normal file
@@ -0,0 +1,41 @@
|
||||
// Filename: config_audio.cxx
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_audio.h"
|
||||
#include "audio_sample.h"
|
||||
#include "audio_music.h"
|
||||
#include <dconfig.h>
|
||||
|
||||
Configure(config_audio);
|
||||
NotifyCategoryDef(audio, "");
|
||||
|
||||
int audio_sample_voices = config_audio.GetInt("audio-sample-voices", 8);
|
||||
int audio_mix_freq = config_audio.GetInt("audio-mix-freq", 11025);
|
||||
string* audio_mode_flags;
|
||||
int audio_driver_select = config_audio.GetInt("audio-driver-select", 0);
|
||||
string* audio_driver_params;
|
||||
|
||||
ConfigureFn(config_audio) {
|
||||
AudioSample::init_type();
|
||||
AudioMusic::init_type();
|
||||
|
||||
Config::ConfigTable::Symbol mode;
|
||||
config_audio.GetAll("audio-mode-flag", mode);
|
||||
Config::ConfigTable::Symbol::iterator i;
|
||||
audio_mode_flags = new string;
|
||||
for (i=mode.begin(); i!=mode.end(); ++i) {
|
||||
if (!audio_mode_flags->empty())
|
||||
*audio_mode_flags += " ";
|
||||
*audio_mode_flags += (*i).Val();
|
||||
}
|
||||
Config::ConfigTable::Symbol parms;
|
||||
config_audio.GetAll("audio-driver-param", parms);
|
||||
audio_driver_params = new string;
|
||||
for (i=parms.begin(); i!=parms.end(); ++i) {
|
||||
if (!audio_driver_params->empty())
|
||||
*audio_driver_params += " ";
|
||||
*audio_driver_params += (*i).Val();
|
||||
}
|
||||
}
|
||||
20
panda/src/audio/config_audio.h
Normal file
20
panda/src/audio/config_audio.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// Filename: config_audio.h
|
||||
// Created by: cary (22Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __CONFIG_AUDIO_H__
|
||||
#define __CONFIG_AUDIO_H__
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <notifyCategoryProxy.h>
|
||||
|
||||
NotifyCategoryDecl(audio, EXPCL_PANDA, EXPTP_PANDA);
|
||||
|
||||
extern int audio_sample_voices;
|
||||
extern int audio_mix_freq;
|
||||
extern string* audio_mode_flags;
|
||||
extern int audio_driver_select;
|
||||
extern string* audio_driver_params;
|
||||
|
||||
#endif /* __CONFIG_AUDIO_H__ */
|
||||
41
panda/src/audio/test_audio.cxx
Normal file
41
panda/src/audio/test_audio.cxx
Normal file
@@ -0,0 +1,41 @@
|
||||
// Filename: test_audio.cxx
|
||||
// Created by: cary (24Sep00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "audio.h"
|
||||
|
||||
#include "config_audio.h"
|
||||
#include <ipc_traits.h>
|
||||
|
||||
int
|
||||
main(int argc, char* argv[]) {
|
||||
if (! AudioPool::verify_sample("test.wav")) {
|
||||
audio_cat->fatal() << "could not locate 'test.wav'" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
AudioSample* sample = AudioPool::load_sample("test.wav");
|
||||
audio_cat->info() << "test.wav is " << sample->length() << "sec long"
|
||||
<< endl;
|
||||
audio_cat->info() << "Playing test.wav" << endl;
|
||||
AudioManager::play(sample);
|
||||
while (sample->status() == AudioSample::PLAYING) {
|
||||
AudioManager::update();
|
||||
ipc_traits::sleep(0, 1000000);
|
||||
}
|
||||
|
||||
// AudioMidi foo("test.midi");
|
||||
if (! AudioPool::verify_music("test.midi")) {
|
||||
audio_cat->fatal() << "could not locate 'test.midi'" << endl;
|
||||
exit(-1);
|
||||
}
|
||||
AudioMusic* music = AudioPool::load_music("test.midi");
|
||||
audio_cat->info() << "Playing test.midi" << endl;
|
||||
AudioManager::play(music);
|
||||
while (music->status() == AudioMusic::PLAYING) {
|
||||
AudioManager::update();
|
||||
ipc_traits::sleep(0, 1000000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
47
panda/src/builder/Sources.pp
Normal file
47
panda/src/builder/Sources.pp
Normal file
@@ -0,0 +1,47 @@
|
||||
#define OTHER_LIBS interrogatedb dconfig dtoolutil dtoolbase
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET builder
|
||||
#define LOCAL_LIBS \
|
||||
linmath gobj sgraph sgattrib graph putil gsgbase mathutil pnmimage \
|
||||
pandabase
|
||||
|
||||
#define SOURCES \
|
||||
builder.I builder.cxx builder.h builderAttrib.I builderAttrib.cxx \
|
||||
builderAttrib.h builderBucket.I builderBucket.cxx builderBucket.h \
|
||||
builderBucketNode.I builderBucketNode.cxx builderBucketNode.h \
|
||||
builderMisc.cxx builderMisc.h builderNormalVisualizer.I \
|
||||
builderNormalVisualizer.cxx builderNormalVisualizer.h \
|
||||
builderPrim.cxx builderPrim.h builderProperties.cxx \
|
||||
builderProperties.h builderTypes.cxx builderTypes.h builderVertex.I \
|
||||
builderVertex.cxx builderVertex.h config_builder.cxx \
|
||||
config_builder.h mesher.cxx mesher.h pta_BuilderC.cxx \
|
||||
pta_BuilderC.h pta_BuilderN.cxx pta_BuilderN.h pta_BuilderTC.cxx \
|
||||
pta_BuilderTC.h pta_BuilderV.cxx pta_BuilderV.h vector_BuilderC.cxx \
|
||||
vector_BuilderC.h vector_BuilderN.cxx vector_BuilderN.h \
|
||||
vector_BuilderTC.cxx vector_BuilderTC.h vector_BuilderV.cxx \
|
||||
vector_BuilderV.h
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
builder.I builder.h builderAttrib.I builderAttrib.h \
|
||||
builderAttribTempl.I builderAttribTempl.h builderBucket.I \
|
||||
builderBucket.h builderBucketNode.I builderBucketNode.h \
|
||||
builderNormalVisualizer.I builderNormalVisualizer.h builderPrim.h \
|
||||
builderPrimTempl.I builderPrimTempl.h builderProperties.h \
|
||||
builderTypes.h builderVertex.I builderVertex.h builderVertexTempl.I \
|
||||
builderVertexTempl.h config_builder.h pta_BuilderC.h pta_BuilderN.h \
|
||||
pta_BuilderTC.h pta_BuilderV.h vector_BuilderC.h vector_BuilderN.h \
|
||||
vector_BuilderTC.h vector_BuilderV.h
|
||||
|
||||
#end lib_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define TARGET test_builder
|
||||
#define LOCAL_LIBS \
|
||||
builder
|
||||
|
||||
#define SOURCES \
|
||||
test_builder.cxx test_builder_data.cxx
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
69
panda/src/builder/builder.I
Normal file
69
panda/src/builder/builder.I
Normal file
@@ -0,0 +1,69 @@
|
||||
// Filename: builder.I
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Builder::add_prim
|
||||
// Access: Public
|
||||
// Description: Adds the indicated nonindexed primitive, along with
|
||||
// its associated bucket, to the builder's internal
|
||||
// structures. This copies all relevant information
|
||||
// into the builder.
|
||||
//
|
||||
// Returns true if the primitive was successfully added,
|
||||
// false if it was invalid for some reason (for
|
||||
// instance, a polygon with two vertices).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Builder::
|
||||
add_prim(const BuilderBucket &bucket,
|
||||
const BuilderPrim &prim) {
|
||||
add_bucket(bucket);
|
||||
return ((BuilderBucketNode &)(*_bi)).add_prim(prim);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Builder::add_prim
|
||||
// Access: Public
|
||||
// Description: Adds the indicated indexed primitive, along with
|
||||
// its associated bucket, to the builder's internal
|
||||
// structures. This copies all relevant information
|
||||
// into the builder.
|
||||
//
|
||||
// Returns true if the primitive was successfully added,
|
||||
// false if it was invalid for some reason (for
|
||||
// instance, a polygon with two vertices).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Builder::
|
||||
add_prim(const BuilderBucket &bucket,
|
||||
const BuilderPrimI &prim) {
|
||||
add_bucket(bucket);
|
||||
return ((BuilderBucketNode &)(*_bi)).add_prim(prim);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Builder::add_prim_nonindexed
|
||||
// Access: Public
|
||||
// Description: Adds the specified indexed primitive as if it were
|
||||
// nonindexed. This simply looks up each coordinate
|
||||
// value on the prim in its associated array and stores
|
||||
// a nonindexed primitive with the actual coordinate
|
||||
// values, instead of the index numbers.
|
||||
//
|
||||
// This is handy for having code that calls the builder
|
||||
// and might want to build either indexed or nonindexed
|
||||
// geometry, as selected by the user at run-time.
|
||||
// Simply build indexed geometry in all cases, then call
|
||||
// either add_prim or add_prim_nonindexed, according to
|
||||
// the user's selection.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool Builder::
|
||||
add_prim_nonindexed(const BuilderBucket &bucket,
|
||||
const BuilderPrimI &prim) {
|
||||
add_bucket(bucket);
|
||||
return ((BuilderBucketNode &)(*_bi)).add_prim_nonindexed(prim);
|
||||
}
|
||||
229
panda/src/builder/builder.cxx
Normal file
229
panda/src/builder/builder.cxx
Normal file
@@ -0,0 +1,229 @@
|
||||
// Filename: builder.cxx
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builder.h"
|
||||
#include "builderFuncs.h"
|
||||
#include "builderMisc.h"
|
||||
|
||||
#include <notify.h>
|
||||
#include <namedNode.h>
|
||||
#include <geomNode.h>
|
||||
#include <renderRelation.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Builder::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Builder::
|
||||
Builder() {
|
||||
_bi = _buckets.end();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Builder::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Builder::
|
||||
~Builder() {
|
||||
// Free all the buckets we allocated. We allocated 'em, we free
|
||||
// 'em.
|
||||
Buckets::iterator bi;
|
||||
for (bi = _buckets.begin();
|
||||
bi != _buckets.end();
|
||||
++bi) {
|
||||
BuilderBucket *bucket = (*bi).get_bucket();
|
||||
delete bucket;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We use the NodeMap class to build up a map of Nodes to GeomNodes.
|
||||
// There may be several buckets that point to the same Node; these
|
||||
// should all be given the same GeomNode, when possible.
|
||||
|
||||
// However, if two buckets have different sets of scene graph
|
||||
// properties--that is, the _trans member is different--they must be
|
||||
// given separate GeomNodes.
|
||||
|
||||
// Furthermore, it's possible to name each bucket. If two buckets
|
||||
// with the same Node pointer have different names, then they should
|
||||
// be given two different GeomNodes.
|
||||
|
||||
class NodeMap : public Namable {
|
||||
public:
|
||||
NodeMap(NamedNode *node, const BuilderBucket *bucket)
|
||||
: _node(node), _bucket(bucket) { }
|
||||
|
||||
bool operator < (const NodeMap &other) const {
|
||||
if (_node != other._node) {
|
||||
return _node < other._node;
|
||||
}
|
||||
if (_bucket->get_name() != other._bucket->get_name()) {
|
||||
return _bucket->get_name() < other._bucket->get_name();
|
||||
}
|
||||
return (_bucket->_trans.compare_to(other._bucket->_trans) < 0);
|
||||
}
|
||||
|
||||
NamedNode *_node;
|
||||
|
||||
// Although a bucket pointer is stored here in the NodeMap class,
|
||||
// you should not use it except to extract the name and/or the
|
||||
// _trans member. Remember, this bucket pointer stands for any of
|
||||
// possibly several bucket pointers, all different, except that they
|
||||
// share the same name and _trans.
|
||||
const BuilderBucket *_bucket;
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Builder::build
|
||||
// Access: Public
|
||||
// Description: Creates Geoms for all the primitives added to all
|
||||
// buckets, and adds them where appropriate to place
|
||||
// them in the scene graph under their respective
|
||||
// parents, and/or returns a single GeomNode that
|
||||
// contains all geometry whose bucket did not reference
|
||||
// a particular scene graph node to parent them to.
|
||||
//
|
||||
// If a bucket's _node pointer was a GeomNode, the
|
||||
// geometry will be added directly to that node. If the
|
||||
// _node pointer was any other kind of node, a GeomNode
|
||||
// will be created and parented to that node, and its
|
||||
// name will be the name of the bucket. In this case,
|
||||
// the name of the bucket can also be used to different
|
||||
// nodes: if two buckets reference the same node, but
|
||||
// have different names, then two different GeomNodes
|
||||
// are created, one with each name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeomNode *Builder::
|
||||
build(const string &default_name) {
|
||||
typedef map<NodeMap, GeomNode *, less<NodeMap> > GeomNodeMap;
|
||||
GeomNodeMap geom_nodes;
|
||||
|
||||
// First, build all the Geoms and create GeomNodes for them. Each
|
||||
// unique Node gets its own GeomNode. If the Node is itself a
|
||||
// GeomNode, that GeomNode is used directly.
|
||||
Buckets::iterator i;
|
||||
for (i = _buckets.begin();
|
||||
i != _buckets.end();
|
||||
++i) {
|
||||
BuilderBucket *bucket = (*i).get_bucket();
|
||||
NamedNode *node = bucket->_node;
|
||||
const string &name = bucket->get_name();
|
||||
GeomNode *geom_node = NULL;
|
||||
|
||||
if (node!=NULL && node->is_of_type(GeomNode::get_class_type())) {
|
||||
// The node is a GeomNode. In this case, we simply use that
|
||||
// node. We can't separate them out by name in this case; we'll
|
||||
// just assign to it the first nonempty name we encounter.
|
||||
geom_node = (GeomNode *)node;
|
||||
|
||||
// Since the caller already created this GeomNode and passed it
|
||||
// in, we'll leave it up to the caller to name the node and set
|
||||
// up the state transitions leading into it.
|
||||
|
||||
} else {
|
||||
// The node is not a GeomNode, so look it up in the map.
|
||||
GeomNodeMap::iterator f = geom_nodes.find(NodeMap(node, bucket));
|
||||
if (f != geom_nodes.end()) {
|
||||
geom_node = (*f).second;
|
||||
|
||||
} else {
|
||||
// No such node/name combination. Create a new one.
|
||||
geom_node = bucket->make_geom_node();
|
||||
if (geom_node != NULL) {
|
||||
geom_nodes[NodeMap(node, bucket)] = geom_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (geom_node != NULL) {
|
||||
(*i).build(geom_node);
|
||||
}
|
||||
}
|
||||
|
||||
// Now go through and parent the geom_nodes under their respective
|
||||
// group nodes. Save out the geom_node associated with a NULL Node;
|
||||
// this one is returned from this function.
|
||||
|
||||
GeomNode *base_geom_node = NULL;
|
||||
|
||||
GeomNodeMap::iterator gi;
|
||||
|
||||
for (gi = geom_nodes.begin();
|
||||
gi != geom_nodes.end();
|
||||
++gi) {
|
||||
const NodeMap &nm = (*gi).first;
|
||||
GeomNode *geom_node = (*gi).second;
|
||||
|
||||
NamedNode *node = nm._node;
|
||||
const string &name = nm._bucket->get_name();
|
||||
const NodeTransitions &trans = nm._bucket->_trans;
|
||||
|
||||
// Assign the name to the geom, if it doesn't have one already.
|
||||
if (!geom_node->has_name()) {
|
||||
if (!name.empty()) {
|
||||
geom_node->set_name(name);
|
||||
|
||||
} else if (!default_name.empty()) {
|
||||
geom_node->set_name(default_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Only reparent the geom_node if it has no parent already.
|
||||
if (geom_node->_parents.empty()) {
|
||||
if (geom_node->get_num_geoms() == 0) {
|
||||
// If there was nothing added, never mind.
|
||||
delete geom_node;
|
||||
|
||||
} else if (node==NULL) {
|
||||
nassertr(base_geom_node == NULL, NULL);
|
||||
base_geom_node = geom_node;
|
||||
|
||||
} else {
|
||||
RenderRelation *arc = new RenderRelation(node, geom_node);
|
||||
// Now, this is our only opportunity to apply the scene-graph
|
||||
// state specified in the bucket to the node: we have created
|
||||
// our own geom_node for these buckets, and we have parented
|
||||
// it to the scene graph.
|
||||
arc->copy_transitions_from(trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return base_geom_node;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Builder::add_bucket
|
||||
// Access: Protected
|
||||
// Description: Adds a new BuilderBucket just like the given one to
|
||||
// the set of all used BuilderBuckets, and makes it the
|
||||
// current bucket. Future primitives will be added to
|
||||
// this bucket.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Builder::
|
||||
add_bucket(const BuilderBucket &bucket) {
|
||||
// Optimization: maybe it's the same bucket we used last time.
|
||||
if (_bi != _buckets.end() &&
|
||||
(*_bi) == BuilderBucketNode((BuilderBucket *)&bucket)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Nope. Look again.
|
||||
_bi = _buckets.find((BuilderBucket *)&bucket);
|
||||
if (_bi == _buckets.end()) {
|
||||
BuilderBucket *new_bucket = bucket.make_copy();
|
||||
_bi = _buckets.insert(new_bucket).first;
|
||||
}
|
||||
}
|
||||
|
||||
198
panda/src/builder/builder.h
Normal file
198
panda/src/builder/builder.h
Normal file
@@ -0,0 +1,198 @@
|
||||
// Filename: builder.h
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDER_H
|
||||
#define BUILDER_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Builder
|
||||
//
|
||||
// The builder accepts as input a loose collection of polygons with
|
||||
// various attributes, sizes, and shapes, and does all the work of
|
||||
// grouping relating polygons and creating triangle strips, etc.,
|
||||
// ultimately storing the resulting optimized geometry into one or
|
||||
// more GeomNodes.
|
||||
//
|
||||
// It is intended that the builder should be the single entry point
|
||||
// for all code wishing to create geometry in the scene graph. The
|
||||
// builder can know about the kinds of geometry that are optimal for a
|
||||
// particular platform, or even about the kinds of geometry that are
|
||||
// available for a given platform. (For instance, perhaps on some
|
||||
// bizarre platform, triangle strips do not exist, but quadstrips are
|
||||
// really fast. User code should not create triangle strips
|
||||
// directly.)
|
||||
//
|
||||
// Actually, there are two fairly separate pieces in this package.
|
||||
// The first is the builder itself, which handles the interface to
|
||||
// user code, and is responsible for collecting polygons from the
|
||||
// caller, sorting them according to their attributes, and creating
|
||||
// Geoms that represent the resulting geometry. The second piece is
|
||||
// the mesher, which receives geometry from the builder and tries to
|
||||
// create optimal triangle strips (or whichever kind of higher-level
|
||||
// structure is most appropriate) from them, which it hands back to
|
||||
// the builder.
|
||||
//
|
||||
// It is possible to use the builder without invoking the mesher, in
|
||||
// which case the builder will create Geoms with the individual prims
|
||||
// exactly as the user passed them in. It is not possible to use the
|
||||
// mesher without first going through the builder.
|
||||
//
|
||||
//
|
||||
// The general system of using the builder is as follows:
|
||||
//
|
||||
// (a) Create a Builder object.
|
||||
//
|
||||
// (b) Iterate through the polygons. For each polygon:
|
||||
//
|
||||
// (c) Create a BuilderBucket object and assign to it the
|
||||
// scene-graph level attributes, such as texture, lighting,
|
||||
// etc. for your polygon. If several polygons share the same
|
||||
// attributes, they can of course use the same bucket. But
|
||||
// there's no reason to be afraid of creating a new bucket
|
||||
// object each time, if that's more convenient.
|
||||
//
|
||||
// (d) Create a BuilderPrim object to describe the polygon. If
|
||||
// the polygon is to have a polygon color or polygon normal,
|
||||
// set these on the BuilderPrim.
|
||||
//
|
||||
// (e) Iterate through the polygon vertices, in counterclockwise
|
||||
// order when viewed from the front of the polygon. For each
|
||||
// vertex:
|
||||
//
|
||||
// (f) Create a BuilderVertex object. If the vertex has a
|
||||
// texture coordinate, normal, or color, set this on the
|
||||
// BuilderVertex.
|
||||
//
|
||||
// (g) Add the BuilderVertex to the BuilderPrim.
|
||||
//
|
||||
// (h) Add the BuilderPrim to the Builder.
|
||||
//
|
||||
// (i) Call Builder::build() and receive your new geometry!
|
||||
//
|
||||
// All of these objects--BuilderBucket, BuilderPrim, and
|
||||
// BuilderVertex--can, and probably should, be ordinary local
|
||||
// variables. When they are added into their respective data
|
||||
// structures they are copied, not referenced, so there's no need to
|
||||
// try to keep them around after that.
|
||||
//
|
||||
// The BuilderBucket is the builder's system for grouping polygons
|
||||
// that share similar characteristings. Polygons that were added to
|
||||
// the builder with equivalent (though not necessarily identical)
|
||||
// buckets may be candidates for joining together into triangle strips
|
||||
// when possible.
|
||||
//
|
||||
//
|
||||
// That's the basic operation. There are lots of fancy features on
|
||||
// top of that.
|
||||
//
|
||||
// * Other kinds of geometry than polygons are supported. Presently,
|
||||
// these are light points and line segments. To add these kinds of
|
||||
// geometry, call set_type() on your BuilderPrim with either
|
||||
// BPT_point or BPT_line.
|
||||
//
|
||||
// * Indexed geometry is supported as well as nonindexed. Indexed
|
||||
// geometry means that the vertices, UV's, etc. are referenced
|
||||
// indirectly; an index number into a table is stored instead of
|
||||
// the actual coordinate values. Indexed geometry may be freely
|
||||
// mixed in with nonindexed geometry; the builder will sort them
|
||||
// out (although each polygon must be either entirely indexed or
|
||||
// entirely nonindexed). To create indexed geometry, use a
|
||||
// BuilderPrimI object, and assign to it a number of BuilderVertexI
|
||||
// vertices. The coordinate values you will assign are ushort
|
||||
// array index numbers. Store the array pointers these refer to in
|
||||
// the BuilderBucket, via set_coords(), set_normals(), etc.
|
||||
//
|
||||
// * The builder is to a certain extent scene-graph aware. In the
|
||||
// normal usage, you give it a bunch of polygons which are all
|
||||
// lumped together, and when you call build() it allocates and
|
||||
// returns a GeomNode which has all of your geometry in it.
|
||||
// However, you can also ask it to distribute the geometry
|
||||
// throughout a pre-existing scene graph. To do this, assign the
|
||||
// _node pointer of your BuilderBucket to point to the node each
|
||||
// polygon belongs under, as you create the polygons. Now when you
|
||||
// call build(), the builder will create all the polygons under the
|
||||
// nodes you indicated, creating new GeomNodes whenever necessary.
|
||||
// The advantage to this method is that you don't have to process
|
||||
// your polygons in scene-graph order; the builder can sort them
|
||||
// out for you. Another advantage is it allows the builder to set
|
||||
// up the state for you, see the next point:
|
||||
//
|
||||
// * It is only when you are taking advantage of the scene-graph
|
||||
// awareness of the builder that the builder can assign the state
|
||||
// transitions (like texturing, etc.) you specify to the geometry
|
||||
// it builds. This is because the state transitions are stored on
|
||||
// the arcs of the scene graph, and in non-scene graph mode there
|
||||
// are no arcs!
|
||||
//
|
||||
// * You can fine-tune the mesher behavior via a number of parameters
|
||||
// on the BuilderBucket. Look in builderProperties.h for these
|
||||
// parameters (BuilderBucket inherits from BuilderProperties).
|
||||
// This is also where you turn the mesher off if you don't want it.
|
||||
//
|
||||
// * You can set global properties on all buckets easily either by
|
||||
// creating your own default BuilderBucket that you use to
|
||||
// initialize each individual BuilderBucket you create, or by
|
||||
// changing the parameters stored in the bucket pointed to by
|
||||
// BuilderBucket::get_default_bucket(), which is what is used to
|
||||
// initialize any BuilderBucket created with a default constructor.
|
||||
// It is suggested that the get_default_bucket() pointer be used to
|
||||
// define global defaults at applications start-up, while a local
|
||||
// default BuilderBucket should be used for local defaults.
|
||||
//
|
||||
// * You can also control the binning behavior, if you have some
|
||||
// particular user-specific parameters you want your geometry to be
|
||||
// grouped on. To do this, subclass from BuilderBucket and
|
||||
// redefine the comparison operator (it's a virtual function), as
|
||||
// well as the make_copy() function.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderAttrib.h"
|
||||
#include "builderBucketNode.h"
|
||||
|
||||
#include <pointerTo.h>
|
||||
|
||||
#include <set>
|
||||
|
||||
|
||||
class GeomNode;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : Builder
|
||||
// Description : The main driver class to the builder package. See
|
||||
// the comments above.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG Builder {
|
||||
public:
|
||||
Builder();
|
||||
~Builder();
|
||||
|
||||
INLINE bool add_prim(const BuilderBucket &bucket,
|
||||
const BuilderPrim &prim);
|
||||
INLINE bool add_prim(const BuilderBucket &bucket,
|
||||
const BuilderPrimI &prim);
|
||||
INLINE bool add_prim_nonindexed(const BuilderBucket &bucket,
|
||||
const BuilderPrimI &prim);
|
||||
|
||||
GeomNode *build(const string &default_name = "");
|
||||
|
||||
protected:
|
||||
void add_bucket(const BuilderBucket &bucket);
|
||||
|
||||
typedef set<BuilderBucketNode, less<BuilderBucketNode> > Buckets;
|
||||
|
||||
Buckets _buckets;
|
||||
Buckets::iterator _bi;
|
||||
};
|
||||
|
||||
#include "builder.I"
|
||||
|
||||
#endif
|
||||
69
panda/src/builder/builderAttrib.I
Normal file
69
panda/src/builder/builderAttrib.I
Normal file
@@ -0,0 +1,69 @@
|
||||
// Filename: builderAttrib.I
|
||||
// Created by: drose (22Jan99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttrib::set_normal_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the normal, without knowing whether the
|
||||
// attribute is indexed or nonindexed. A nonindexed
|
||||
// attribute will look up the index in the array and
|
||||
// store the resulting value, while an indexed attribute
|
||||
// will just store the index number (which assumes the
|
||||
// array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderAttrib::
|
||||
set_normal_value(const BuilderN *array, ushort index) {
|
||||
set_normal(array[index]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttrib::set_color_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the color, without knowing whether the
|
||||
// attribute is indexed or nonindexed. A nonindexed
|
||||
// attribute will look up the index in the array and
|
||||
// store the resulting value, while an indexed attribute
|
||||
// will just store the index number (which assumes the
|
||||
// array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderAttrib::
|
||||
set_color_value(const BuilderC *array, ushort index) {
|
||||
set_color(array[index]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribI::set_normal_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the normal, without knowing whether the
|
||||
// attribute is indexed or nonindexed. A nonindexed
|
||||
// attribute will look up the index in the array and
|
||||
// store the resulting value, while an indexed attribute
|
||||
// will just store the index number (which assumes the
|
||||
// array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderAttribI::
|
||||
set_normal_value(const BuilderN *, ushort index) {
|
||||
set_normal(index);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribI::set_color_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the color, without knowing whether the
|
||||
// attribute is indexed or nonindexed. A nonindexed
|
||||
// attribute will look up the index in the array and
|
||||
// store the resulting value, while an indexed attribute
|
||||
// will just store the index number (which assumes the
|
||||
// array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderAttribI::
|
||||
set_color_value(const BuilderC *, ushort index) {
|
||||
set_color(index);
|
||||
}
|
||||
12
panda/src/builder/builderAttrib.cxx
Normal file
12
panda/src/builder/builderAttrib.cxx
Normal file
@@ -0,0 +1,12 @@
|
||||
// Filename: builderAttrib.cxx
|
||||
// Created by: drose (11May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderAttrib.h"
|
||||
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma implementation
|
||||
#endif
|
||||
59
panda/src/builder/builderAttrib.h
Normal file
59
panda/src/builder/builderAttrib.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// Filename: builderAttrib.h
|
||||
// Created by: drose (22Jan99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERATTRIB_H
|
||||
#define BUILDERATTRIB_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BuilderAttrib, BuilderAttribI
|
||||
//
|
||||
// This is the parent class of both BuilderVertex and BuilderPrim, and
|
||||
// contains the attribute values which may be set on either of them:
|
||||
// specifically, normal, color, and pixel size. (Pixel size is the
|
||||
// thickness of the lines, for a polygon or a line, or the size of the
|
||||
// point, in pixels.)
|
||||
//
|
||||
// Like BuilderPrim and BuilderVertex, the two classes BuilderAttrib
|
||||
// and BuilderAttribI are actually both instantiations of the same
|
||||
// template class, BuilderAttribTempl.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderAttribTempl.h"
|
||||
|
||||
#define BUILDERATTRIBTEMPL_BUILDERV BuilderAttribTempl<BuilderV, BuilderN, BuilderTC, BuilderC>
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, BUILDERATTRIBTEMPL_BUILDERV);
|
||||
#define BUILDERATTRIBTEMPL_USHORT BuilderAttribTempl<ushort, ushort, ushort, ushort>
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, BUILDERATTRIBTEMPL_USHORT);
|
||||
|
||||
class EXPCL_PANDAEGG BuilderAttrib
|
||||
: public BuilderAttribTempl<BuilderV, BuilderN, BuilderTC, BuilderC> {
|
||||
public:
|
||||
BuilderAttrib() {}
|
||||
|
||||
INLINE void set_normal_value(const BuilderN *array, ushort index);
|
||||
INLINE void set_color_value(const BuilderC *array, ushort index);
|
||||
};
|
||||
|
||||
class EXPCL_PANDAEGG BuilderAttribI
|
||||
: public BuilderAttribTempl<ushort, ushort, ushort, ushort> {
|
||||
public:
|
||||
BuilderAttribI() {}
|
||||
|
||||
INLINE void set_normal_value(const BuilderN *array, ushort index);
|
||||
INLINE void set_color_value(const BuilderC *array, ushort index);
|
||||
};
|
||||
|
||||
#include "builderAttrib.I"
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#endif
|
||||
244
panda/src/builder/builderAttribTempl.I
Normal file
244
panda/src/builder/builderAttribTempl.I
Normal file
@@ -0,0 +1,244 @@
|
||||
// Filename: builderAttribTempl.I
|
||||
// Created by: drose (17Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
BuilderAttribTempl() {
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::Copy constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
BuilderAttribTempl(const BuilderAttribTempl ©) {
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::Copy assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT> &BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
operator = (const BuilderAttribTempl<VT, NT, TT, CT> ©) {
|
||||
_normal = copy._normal;
|
||||
_color = copy._color;
|
||||
_pixel_size = copy._pixel_size;
|
||||
_flags = copy._flags;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::clear
|
||||
// Access: Public
|
||||
// Description: Resets the attribute flags to their original, empty
|
||||
// state--where no attributes have been applied.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT> &BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
clear() {
|
||||
_flags = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::has_normal
|
||||
// Access: Public
|
||||
// Description: Returns true if the attribute has a normal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
has_normal() const {
|
||||
return (_flags & BAF_normal)!=0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::get_normal
|
||||
// Access: Public
|
||||
// Description: Returns the attribute's normal. It is an error to
|
||||
// call this without first verifying that has_normal() is
|
||||
// true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT>::NType BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
get_normal() const {
|
||||
nassertr(has_normal(), _normal);
|
||||
return _normal;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::set_normal
|
||||
// Access: Public
|
||||
// Description: Resets the attribute's normal.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT> &BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
set_normal(const NType &n) {
|
||||
_flags |= BAF_normal;
|
||||
_normal = n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::has_color
|
||||
// Access: Public
|
||||
// Description: Returns true if the attribute has a color.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
has_color() const {
|
||||
return (_flags & BAF_color)!=0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::get_color
|
||||
// Access: Public
|
||||
// Description: Returns the attribute's color. It is an error to
|
||||
// call this without first verifying that has_color() is
|
||||
// true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT>::CType BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
get_color() const {
|
||||
nassertr(has_color(), _color);
|
||||
return _color;
|
||||
}
|
||||
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::set_color
|
||||
// Access: Public
|
||||
// Description: Resets the attribute's color.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT> &BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
set_color(const CType &c) {
|
||||
_flags |= BAF_color;
|
||||
_color = c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::has_pixel_size
|
||||
// Access: Public
|
||||
// Description: Returns true if the attribute has a pixel_size.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
has_pixel_size() const {
|
||||
return (_flags & BAF_pixel_size)!=0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::get_pixel_size
|
||||
// Access: Public
|
||||
// Description: Returns the attribute's pixel_size. It is an error to
|
||||
// call this without first verifying that has_pixel_size() is
|
||||
// true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE float BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
get_pixel_size() const {
|
||||
nassertr(has_pixel_size(), _pixel_size);
|
||||
return _pixel_size;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::set_pixel_size
|
||||
// Access: Public
|
||||
// Description: Resets the attribute's pixel_size.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderAttribTempl<VT, NT, TT, CT> &BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
set_pixel_size(float s) {
|
||||
_flags |= BAF_pixel_size;
|
||||
_pixel_size = s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::operator ==
|
||||
// Access: Public
|
||||
// Description: Assigns an ordering to the vertices. This is used by
|
||||
// the Mesher to group identical vertices. This assumes
|
||||
// that all vertices in the locus of consideration will
|
||||
// share the same state: with or without normals,
|
||||
// texcoords, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
operator == (const BuilderAttribTempl<VT, NT, TT, CT> &other) const {
|
||||
if (has_normal() && !(_normal == other._normal))
|
||||
return false;
|
||||
|
||||
if (has_color() && !(_color == other._color))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::operator <
|
||||
// Access: Public
|
||||
// Description: Assigns an ordering to the vertices. This is used by
|
||||
// the Mesher to group identical vertices. This assumes
|
||||
// that all vertices in the locus of consideration will
|
||||
// share the same state: with or without normals,
|
||||
// texcoords, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
operator < (const BuilderAttribTempl<VT, NT, TT, CT> &other) const {
|
||||
if (has_normal() && !(_normal == other._normal))
|
||||
return _normal < other._normal;
|
||||
|
||||
if (has_color() && !(_color == other._color))
|
||||
return _color < other._color;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderAttribTempl::output
|
||||
// Access: Public
|
||||
// Description: Formats the attribs for output in some sensible way.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE ostream &BuilderAttribTempl<VT, NT, TT, CT>::
|
||||
output(ostream &out) const {
|
||||
if (this!=NULL) {
|
||||
if (has_normal()) {
|
||||
out << " normal " << get_normal();
|
||||
}
|
||||
|
||||
if (has_color()) {
|
||||
out << " color " << get_color();
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
70
panda/src/builder/builderAttribTempl.h
Normal file
70
panda/src/builder/builderAttribTempl.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// Filename: builderAttribTempl.h
|
||||
// Created by: drose (17Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifndef BUILDERATTRIBTEMPL_H
|
||||
#define BUILDERATTRIBTEMPL_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderTypes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderAttribTempl
|
||||
// Description : The main body of BuilderAttrib and BuilderAttribI,
|
||||
// and the base class for BuilderVertexTempl and
|
||||
// BuilderPrimTempl, this class defines the attributes
|
||||
// that may be specified for either vertices or
|
||||
// primitives.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
class BuilderAttribTempl {
|
||||
public:
|
||||
typedef VT VType;
|
||||
typedef NT NType;
|
||||
typedef TT TType;
|
||||
typedef CT CType;
|
||||
|
||||
INLINE BuilderAttribTempl();
|
||||
INLINE BuilderAttribTempl(const BuilderAttribTempl ©);
|
||||
INLINE BuilderAttribTempl &operator = (const BuilderAttribTempl ©);
|
||||
|
||||
INLINE BuilderAttribTempl &clear();
|
||||
|
||||
INLINE bool has_normal() const;
|
||||
INLINE NType get_normal() const;
|
||||
INLINE BuilderAttribTempl &set_normal(const NType &n);
|
||||
|
||||
INLINE bool has_color() const;
|
||||
INLINE CType get_color() const;
|
||||
INLINE BuilderAttribTempl &set_color(const CType &c);
|
||||
|
||||
INLINE bool has_pixel_size() const;
|
||||
INLINE float get_pixel_size() const;
|
||||
INLINE BuilderAttribTempl &set_pixel_size(float s);
|
||||
|
||||
INLINE bool operator == (const BuilderAttribTempl &other) const;
|
||||
INLINE bool operator < (const BuilderAttribTempl &other) const;
|
||||
|
||||
INLINE ostream &output(ostream &out) const;
|
||||
|
||||
protected:
|
||||
NType _normal;
|
||||
CType _color;
|
||||
float _pixel_size;
|
||||
int _flags;
|
||||
};
|
||||
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE ostream &operator << (ostream &out,
|
||||
const BuilderAttribTempl<VT, NT, TT, CT> &attrib) {
|
||||
return attrib.output(out);
|
||||
}
|
||||
|
||||
#include "builderAttribTempl.I"
|
||||
|
||||
#endif
|
||||
|
||||
117
panda/src/builder/builderBucket.I
Normal file
117
panda/src/builder/builderBucket.I
Normal file
@@ -0,0 +1,117 @@
|
||||
// Filename: builderBucket.I
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::set_coords
|
||||
// Access: Public
|
||||
// Description: Sets the array that will be used to define the
|
||||
// vertices for any indexed geometry that is associated
|
||||
// with this bucket.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderBucket::
|
||||
set_coords(const PTA_Vertexf &coords) {
|
||||
_coords = coords;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::get_coords
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_Vertexf BuilderBucket::
|
||||
get_coords() const {
|
||||
return _coords;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::set_normals
|
||||
// Access: Public
|
||||
// Description: Sets the array that will be used to define the
|
||||
// normals for any indexed geometry that is associated
|
||||
// with this bucket.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderBucket::
|
||||
set_normals(const PTA_Normalf &normals) {
|
||||
_normals = normals;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::get_normals
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_Normalf BuilderBucket::
|
||||
get_normals() const {
|
||||
return _normals;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::set_texcoords
|
||||
// Access: Public
|
||||
// Description: Sets the array that will be used to define the
|
||||
// texture coordinates for any indexed geometry that is
|
||||
// associated with this bucket.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderBucket::
|
||||
set_texcoords(const PTA_TexCoordf &texcoords) {
|
||||
_texcoords = texcoords;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::get_texcoords
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_TexCoordf BuilderBucket::
|
||||
get_texcoords() const {
|
||||
return _texcoords;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::set_colors
|
||||
// Access: Public
|
||||
// Description: Sets the array that will be used to define the
|
||||
// colors for any indexed geometry that is associated
|
||||
// with this bucket.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderBucket::
|
||||
set_colors(const PTA_Colorf &colors) {
|
||||
_colors = colors;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::get_colors
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PTA_Colorf BuilderBucket::
|
||||
get_colors() const {
|
||||
return _colors;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::get_default_bucket
|
||||
// Access: Public, Static
|
||||
// Description: Returns a pointer to the BuilderBucket that is used
|
||||
// to initialize any BuilderBuckets created with a
|
||||
// default constructor. This is just a convenient way
|
||||
// to set some global parameters.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderBucket *BuilderBucket::
|
||||
get_default_bucket() {
|
||||
if (_default_bucket==NULL) {
|
||||
_default_bucket = new BuilderBucket(true);
|
||||
}
|
||||
return _default_bucket;
|
||||
}
|
||||
240
panda/src/builder/builderBucket.cxx
Normal file
240
panda/src/builder/builderBucket.cxx
Normal file
@@ -0,0 +1,240 @@
|
||||
// Filename: builderBucket.cxx
|
||||
// Created by: drose (10Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderAttrib.h"
|
||||
#include "builderBucket.h"
|
||||
#include "builderFuncs.h"
|
||||
#include "builderMisc.h"
|
||||
|
||||
#include <namedNode.h>
|
||||
#include <geomNode.h>
|
||||
|
||||
BuilderBucket *BuilderBucket::_default_bucket = NULL;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BuilderBucket::
|
||||
BuilderBucket() {
|
||||
_node = NULL;
|
||||
(*this) = (*get_default_bucket());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::Copy constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BuilderBucket::
|
||||
BuilderBucket(const BuilderBucket ©) {
|
||||
_node = NULL;
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::Copy assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BuilderBucket &BuilderBucket::
|
||||
operator = (const BuilderBucket ©) {
|
||||
((BuilderProperties &)*this) = (BuilderProperties &)copy;
|
||||
|
||||
// setGState(copy._state);
|
||||
set_name(copy.get_name());
|
||||
set_coords(copy._coords);
|
||||
set_normals(copy._normals);
|
||||
set_texcoords(copy._texcoords);
|
||||
set_colors(copy._colors);
|
||||
|
||||
_node = copy._node;
|
||||
_drawBin = copy._drawBin;
|
||||
_drawOrder = copy._drawOrder;
|
||||
|
||||
_trans = copy._trans;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BuilderBucket::
|
||||
~BuilderBucket() {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::make_copy
|
||||
// Access: Public, Virtual
|
||||
// Description: Allocates and returns a new copy of this object. If
|
||||
// you are subclassing from BuilderBucket, you must
|
||||
// redefine this to return an instance of your new
|
||||
// subclass, because the Builder will call this function
|
||||
// to get its own copy.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BuilderBucket *BuilderBucket::
|
||||
make_copy() const {
|
||||
return new BuilderBucket(*this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::make_geom_node
|
||||
// Access: Public, Virtual
|
||||
// Description: Called by the builder when it is time to create a new
|
||||
// GeomNode. This function should allocate and return a
|
||||
// new GeomNode suitable for adding geometry to. You
|
||||
// may redefine it to return a subclass of GeomNode, or
|
||||
// to do some initialization to the node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GeomNode *BuilderBucket::
|
||||
make_geom_node() {
|
||||
return new GeomNode;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::done_geom
|
||||
// Access: Public, Virtual
|
||||
// Description: Called after all the geometry has been added to the
|
||||
// Geom. This is just a hook for the user to redefine
|
||||
// to do any post-processing that may be desired on the
|
||||
// geometry. It may deallocate it and return a new
|
||||
// copy. If it returns NULL, the geom is discarded.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
Geom *BuilderBucket::
|
||||
done_geom(Geom *geom) {
|
||||
return geom;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::Ordering operator
|
||||
// Access: Public, Virtual
|
||||
// Description: Defines an arbitrary ordering among different
|
||||
// buckets, and groups identical buckets together.
|
||||
// (Buckets a and b are identical if !(a < b) and !(b <
|
||||
// a).)
|
||||
//
|
||||
// The actual order between different buckets is
|
||||
// arbitrary and largely irrelevant, so long as it is
|
||||
// consistent. That is, if (a < b) and (b < c), it must
|
||||
// also be true that (a < c). Also, if (a < b), it
|
||||
// cannot be true that (b < a).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BuilderBucket::
|
||||
operator < (const BuilderBucket &other) const {
|
||||
if (get_name() != other.get_name()) {
|
||||
return get_name() < other.get_name();
|
||||
}
|
||||
|
||||
if (_node != other._node)
|
||||
return _node < other._node;
|
||||
|
||||
if (_coords != other._coords)
|
||||
return _coords < other._coords;
|
||||
if (_normals != other._normals)
|
||||
return _normals < other._normals;
|
||||
if (_texcoords != other._texcoords)
|
||||
return _texcoords < other._texcoords;
|
||||
if (_colors != other._colors)
|
||||
return _colors < other._colors;
|
||||
|
||||
if (_drawBin != other._drawBin)
|
||||
return _drawBin < other._drawBin;
|
||||
if (_drawOrder != other._drawOrder)
|
||||
return _drawOrder < other._drawOrder;
|
||||
|
||||
int compare = _trans.compare_to(other._trans);
|
||||
if (compare != 0) {
|
||||
return (compare < 0);
|
||||
}
|
||||
|
||||
return BuilderProperties::operator < (other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::output
|
||||
// Access: Public, Virtual
|
||||
// Description: Formats the bucket for output in some sensible way.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BuilderBucket::
|
||||
output(ostream &out) const {
|
||||
out << "Bucket \"" << get_name() << "\"";
|
||||
|
||||
if (_node != (NamedNode *)NULL) {
|
||||
out << " attached to " << *_node << "\n";
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
|
||||
if (_coords != (Vertexf *)NULL) {
|
||||
out << "_coords = " << (void *)_coords << "\n";
|
||||
}
|
||||
|
||||
if (_normals != (Normalf *)NULL) {
|
||||
out << "_normals = " << (void *)_normals << "\n";
|
||||
}
|
||||
|
||||
if (_texcoords != (TexCoordf *)NULL) {
|
||||
out << "_texcoords = " << (void *)_texcoords << "\n";
|
||||
}
|
||||
|
||||
if (_colors != (Colorf *)NULL) {
|
||||
out << "_colors = " << (void *)_colors << "\n";
|
||||
}
|
||||
|
||||
if (_drawBin != -1) {
|
||||
out << "_drawBin = " << _drawBin << "\n";
|
||||
}
|
||||
|
||||
if (_drawOrder != 0) {
|
||||
out << "_drawOrder = " << _drawOrder << "\n";
|
||||
}
|
||||
|
||||
BuilderProperties::output(out);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucket::private Constructor
|
||||
// Access: Private
|
||||
// Description: This special constructor is used only to initialize
|
||||
// the _default_bucket pointer. It sets up the initial
|
||||
// defaults. The normal constructor copies from this
|
||||
// instance.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BuilderBucket::
|
||||
BuilderBucket(int) {
|
||||
_node = NULL;
|
||||
|
||||
_drawBin = -1;
|
||||
_drawOrder = 0;
|
||||
|
||||
// From BuilderProperties
|
||||
_mesh = true;
|
||||
_retesselate_coplanar = true;
|
||||
_show_tstrips = false;
|
||||
_show_qsheets = false;
|
||||
_show_quads = false;
|
||||
_show_normals = false;
|
||||
_normal_color._v.set(1.0, 0.0, 0.0, 1.0);
|
||||
_normal_scale = 1.0;
|
||||
_subdivide_polys = true;
|
||||
_coplanar_threshold = 0.01;
|
||||
|
||||
_unroll_fans = true;
|
||||
_consider_fans = true;
|
||||
_max_tfan_angle = 40.0;
|
||||
_min_tfan_tris = 0;
|
||||
}
|
||||
104
panda/src/builder/builderBucket.h
Normal file
104
panda/src/builder/builderBucket.h
Normal file
@@ -0,0 +1,104 @@
|
||||
// Filename: builderBucket.h
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERBUCKET_H
|
||||
#define BUILDERBUCKET_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderProperties.h"
|
||||
|
||||
#include <namable.h>
|
||||
#include <pointerToArray.h>
|
||||
#include <luse.h>
|
||||
#include <nodeTransitions.h>
|
||||
#include <pta_Vertexf.h>
|
||||
#include <pta_Normalf.h>
|
||||
#include <pta_Colorf.h>
|
||||
#include <pta_TexCoordf.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
class NamedNode;
|
||||
class Geom;
|
||||
class GeomNode;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderBucket
|
||||
// Description : The main grouping tool for BuilderPrims. See the
|
||||
// comments at the beginning of builder.h.
|
||||
//
|
||||
// As each primitive is added to the builder, it is
|
||||
// associated with a bucket. The bucket stores the
|
||||
// scene-graph properties of the primitive, and is used
|
||||
// to identify primitives that have the same properties
|
||||
// and thus may be joined into a common triangle strip.
|
||||
//
|
||||
// This grouping is done via the ordering operator, <,
|
||||
// which defines an arbitrary ordering for buckets and
|
||||
// identifies those buckets which are equivalent to each
|
||||
// other. By subclassing off of BuilderBucket and
|
||||
// redefining this operator, you can change the grouping
|
||||
// behavior to suit your needs, if necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderBucket : public BuilderProperties, public Namable {
|
||||
public:
|
||||
BuilderBucket();
|
||||
BuilderBucket(const BuilderBucket ©);
|
||||
BuilderBucket &operator = (const BuilderBucket ©);
|
||||
virtual ~BuilderBucket();
|
||||
|
||||
virtual BuilderBucket *make_copy() const;
|
||||
virtual GeomNode *make_geom_node();
|
||||
virtual Geom *done_geom(Geom *geom);
|
||||
|
||||
virtual bool operator < (const BuilderBucket &other) const;
|
||||
|
||||
INLINE void set_coords(const PTA_Vertexf &coords);
|
||||
INLINE PTA_Vertexf get_coords() const;
|
||||
|
||||
INLINE void set_normals(const PTA_Normalf &normals);
|
||||
INLINE PTA_Normalf get_normals() const;
|
||||
|
||||
INLINE void set_texcoords(const PTA_TexCoordf &texcoords);
|
||||
INLINE PTA_TexCoordf get_texcoords() const;
|
||||
|
||||
INLINE void set_colors(const PTA_Colorf &colors);
|
||||
INLINE PTA_Colorf get_colors() const;
|
||||
|
||||
INLINE static BuilderBucket *get_default_bucket();
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
NamedNode *_node;
|
||||
|
||||
short _drawBin;
|
||||
unsigned int _drawOrder;
|
||||
|
||||
NodeTransitions _trans;
|
||||
|
||||
protected:
|
||||
PTA_Vertexf _coords;
|
||||
PTA_Normalf _normals;
|
||||
PTA_TexCoordf _texcoords;
|
||||
PTA_Colorf _colors;
|
||||
|
||||
static BuilderBucket *_default_bucket;
|
||||
|
||||
private:
|
||||
BuilderBucket(int);
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const BuilderBucket &bucket) {
|
||||
bucket.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "builderBucket.I"
|
||||
|
||||
#endif
|
||||
|
||||
92
panda/src/builder/builderBucketNode.I
Normal file
92
panda/src/builder/builderBucketNode.I
Normal file
@@ -0,0 +1,92 @@
|
||||
// Filename: builderBucketNode.I
|
||||
// Created by: drose (10Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderBucketNode::
|
||||
BuilderBucketNode(BuilderBucket *bucket) : _bucket(bucket) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::Copy constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderBucketNode::
|
||||
BuilderBucketNode(const BuilderBucketNode ©) {
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::Copy assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderBucketNode::
|
||||
operator = (const BuilderBucketNode ©) {
|
||||
_bucket = copy._bucket;
|
||||
_prims = copy._prims;
|
||||
_iprims = copy._iprims;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::add_prim_nonindexed
|
||||
// Access: Public
|
||||
// Description: Adds the indicated indexed primitive to the bucket as
|
||||
// if it were nonindexed, and returns true if the
|
||||
// primitive was valid. Intended to be called from
|
||||
// Builder::add_prim_nonindexed().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool BuilderBucketNode::
|
||||
add_prim_nonindexed(const BuilderPrimI &prim) {
|
||||
BuilderPrim nonindexed;
|
||||
nonindexed.nonindexed_copy(prim, *_bucket);
|
||||
return add_prim(nonindexed);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::get_bucket
|
||||
// Access: Public
|
||||
// Description: Returns the BuilderBucket object associated with this
|
||||
// node.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderBucket *BuilderBucketNode::
|
||||
get_bucket() const {
|
||||
return _bucket;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::Ordering operator
|
||||
// Access: Public
|
||||
// Description: Returns true if this bucket precedes the indicated
|
||||
// one in ordering. This function is used by the STL
|
||||
// set in the Builder object to sort buckets into order,
|
||||
// and to collect similar buckets together.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool BuilderBucketNode::
|
||||
operator < (const BuilderBucketNode &other) const {
|
||||
return (*_bucket) < (*other._bucket);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::Equivalence operator
|
||||
// Access: Public
|
||||
// Description: Returns true if the two buckets are equivalent, based
|
||||
// on the ordering operator, above.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool BuilderBucketNode::
|
||||
operator == (const BuilderBucketNode &other) const {
|
||||
return !((*_bucket) < (*other._bucket) ||
|
||||
(*other._bucket) < (*_bucket));
|
||||
}
|
||||
87
panda/src/builder/builderBucketNode.cxx
Normal file
87
panda/src/builder/builderBucketNode.cxx
Normal file
@@ -0,0 +1,87 @@
|
||||
// Filename: builderBucketNode.cxx
|
||||
// Created by: drose (10Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderFuncs.h"
|
||||
#include "builderBucketNode.h"
|
||||
|
||||
#include <geomNode.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::add_prim
|
||||
// Access: Public
|
||||
// Description: Adds the indicated indexed primitive to the
|
||||
// bucket, and returns true if the primitive was valid.
|
||||
// Intended to be called from Builder::add_prim().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BuilderBucketNode::
|
||||
add_prim(const BuilderPrim &prim) {
|
||||
bool result = expand(prim, *_bucket, inserter(_prims, _prims.begin()));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::add_prim
|
||||
// Access: Public
|
||||
// Description: Adds the indicated nonindexed primitive to the
|
||||
// bucket, and returns true if the primitive was valid.
|
||||
// Intended to be called from Builder::add_prim().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BuilderBucketNode::
|
||||
add_prim(const BuilderPrimI &prim) {
|
||||
bool result = expand(prim, *_bucket, inserter(_iprims, _iprims.begin()));
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderBucketNode::build
|
||||
// Access: Public
|
||||
// Description: Builds all the geometry assigned to this particular
|
||||
// bucket, and assigns it to the indicated GeomNode.
|
||||
// Returns the number of Geoms created.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BuilderBucketNode::
|
||||
build(GeomNode *geom_node) const {
|
||||
int count = 0;
|
||||
|
||||
{
|
||||
// First, the nonindexed.
|
||||
Prims::const_iterator pi, last_pi;
|
||||
last_pi = _prims.begin();
|
||||
|
||||
for (pi = _prims.begin();
|
||||
pi != _prims.end();
|
||||
++pi) {
|
||||
if ((*last_pi) < (*pi)) {
|
||||
count += mesh_and_build(last_pi, pi, *_bucket, geom_node,
|
||||
(BuilderPrim *)0);
|
||||
last_pi = pi;
|
||||
}
|
||||
}
|
||||
count += mesh_and_build(last_pi, pi, *_bucket, geom_node,
|
||||
(BuilderPrim *)0);
|
||||
}
|
||||
|
||||
{
|
||||
// Then, the indexed.
|
||||
IPrims::const_iterator pi, last_pi;
|
||||
last_pi = _iprims.begin();
|
||||
|
||||
for (pi = _iprims.begin();
|
||||
pi != _iprims.end();
|
||||
++pi) {
|
||||
if ((*last_pi) < (*pi)) {
|
||||
count += mesh_and_build(last_pi, pi, *_bucket, geom_node,
|
||||
(BuilderPrimI *)0);
|
||||
last_pi = pi;
|
||||
}
|
||||
}
|
||||
count += mesh_and_build(last_pi, pi, *_bucket, geom_node,
|
||||
(BuilderPrimI *)0);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
58
panda/src/builder/builderBucketNode.h
Normal file
58
panda/src/builder/builderBucketNode.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// Filename: builderBucketNode.h
|
||||
// Created by: drose (10Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERBUCKETNODE_H
|
||||
#define BUILDERBUCKETNODE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderPrim.h"
|
||||
#include "builderBucket.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
class GeomNode;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderBucketNode
|
||||
// Description : This is a wrapper class around BuilderBucket, used by
|
||||
// the Builder class. It stores a pointer to a
|
||||
// BuilderBucket object, as well as lists of the
|
||||
// primitives that have been added to it.
|
||||
//
|
||||
// There are no functions in this class that are
|
||||
// intended to be called directly by user code; instead,
|
||||
// use the interface provided by Builder.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderBucketNode {
|
||||
public:
|
||||
INLINE BuilderBucketNode(BuilderBucket *bucket);
|
||||
INLINE BuilderBucketNode(const BuilderBucketNode ©);
|
||||
INLINE void operator = (const BuilderBucketNode ©);
|
||||
|
||||
bool add_prim(const BuilderPrim &prim);
|
||||
bool add_prim(const BuilderPrimI &prim);
|
||||
INLINE bool add_prim_nonindexed(const BuilderPrimI &prim);
|
||||
|
||||
INLINE BuilderBucket *get_bucket() const;
|
||||
|
||||
INLINE bool operator < (const BuilderBucketNode &other) const;
|
||||
INLINE bool operator == (const BuilderBucketNode &other) const;
|
||||
|
||||
int build(GeomNode *geom_node) const;
|
||||
|
||||
protected:
|
||||
typedef multiset<BuilderPrim, less<BuilderPrim> > Prims;
|
||||
typedef multiset<BuilderPrimI, less<BuilderPrimI> > IPrims;
|
||||
|
||||
BuilderBucket *_bucket;
|
||||
Prims _prims;
|
||||
IPrims _iprims;
|
||||
};
|
||||
|
||||
#include "builderBucketNode.I"
|
||||
|
||||
#endif
|
||||
908
panda/src/builder/builderFuncs.I
Normal file
908
panda/src/builder/builderFuncs.I
Normal file
@@ -0,0 +1,908 @@
|
||||
// Filename: builderFuncs.cxx
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderPrim.h"
|
||||
#include "mesherTempl.h"
|
||||
#include "builderNormalVisualizer.h"
|
||||
#include "config_builder.h"
|
||||
|
||||
#include <geom.h>
|
||||
#include <geomprimitives.h>
|
||||
#include <geomNode.h>
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef PENV_WIN32
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32_VC
|
||||
struct Vtx {
|
||||
int index;
|
||||
BuilderV coord;
|
||||
struct Vtx *next;
|
||||
};
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: decomp_concave
|
||||
// Description: Decomposes a concave polygon into triangles. Returns
|
||||
// true if successful, false if the polygon is
|
||||
// self-intersecting.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType, class OutputIterator>
|
||||
static bool
|
||||
decomp_concave(const PrimType &prim, BuilderBucket &bucket,
|
||||
OutputIterator result,
|
||||
int asum, int x, int y) {
|
||||
#ifndef WIN32_VC
|
||||
struct Vtx {
|
||||
int index;
|
||||
BuilderV coord;
|
||||
struct Vtx *next;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define VX(p, c) p->coord[c]
|
||||
|
||||
vector<PrimType> output_prims;
|
||||
|
||||
Vtx *p0, *p1, *p2, *t0, *vert;
|
||||
Vtx *m[3];
|
||||
float xmin, xmax, ymin, ymax;
|
||||
int i, init, csum, chek;
|
||||
float a[3], b[3], c[3], s[3];
|
||||
|
||||
int num_verts = prim.get_num_verts();
|
||||
nassertr(num_verts >= 3, false);
|
||||
|
||||
/* Make linked list of verts */
|
||||
vert = (Vtx *) alloca(sizeof(Vtx));
|
||||
vert->index = 0;
|
||||
vert->coord = prim.get_vertex(0).get_coord_value(bucket);
|
||||
p1 = vert;
|
||||
|
||||
for (i = 1; i < num_verts; i++) {
|
||||
p0 = (Vtx *) alloca(sizeof(Vtx));
|
||||
p0->index = i;
|
||||
p0->coord = prim.get_vertex(i).get_coord_value(bucket);
|
||||
// There shouldn't be two consecutive identical vertices. If
|
||||
// there are, skip one.
|
||||
if (!(p0->coord == p1->coord)) {
|
||||
p1->next = p0;
|
||||
p1 = p0;
|
||||
}
|
||||
}
|
||||
p1->next = vert;
|
||||
|
||||
p0 = vert;
|
||||
p1 = p0->next;
|
||||
p2 = p1->next;
|
||||
m[0] = p0;
|
||||
m[1] = p1;
|
||||
m[2] = p2;
|
||||
chek = 0;
|
||||
|
||||
while (p0 != p2->next) {
|
||||
/* Polygon is self-intersecting so punt */
|
||||
if (chek &&
|
||||
m[0] == p0 &&
|
||||
m[1] == p1 &&
|
||||
m[2] == p2) {
|
||||
|
||||
// builder_cat.info() << "Could not decompose concave polygon!";
|
||||
return false;
|
||||
}
|
||||
|
||||
chek = 1;
|
||||
|
||||
a[0] = VX(p1, y) - VX(p2, y);
|
||||
b[0] = VX(p2, x) - VX(p1, x);
|
||||
a[2] = VX(p0, y) - VX(p1, y);
|
||||
b[2] = VX(p1, x) - VX(p0, x);
|
||||
|
||||
csum = ((b[0] * a[2] - b[2] * a[0] >= 0.0) ? 1 : 0);
|
||||
|
||||
if (csum ^ asum) {
|
||||
/* current angle is concave */
|
||||
p0 = p1;
|
||||
p1 = p2;
|
||||
p2 = p2->next;
|
||||
|
||||
} else {
|
||||
/* current angle is convex */
|
||||
xmin = (VX(p0, x) < VX(p1, x)) ? VX(p0, x) : VX(p1, x);
|
||||
if (xmin > VX(p2, x))
|
||||
xmin = VX(p2, x);
|
||||
|
||||
xmax = (VX(p0, x) > VX(p1, x)) ? VX(p0, x) : VX(p1, x);
|
||||
if (xmax < VX(p2, x))
|
||||
xmax = VX(p2, x);
|
||||
|
||||
ymin = (VX(p0, y) < VX(p1, y)) ? VX(p0, y) : VX(p1, y);
|
||||
if (ymin > VX(p2, y))
|
||||
ymin = VX(p2, y);
|
||||
|
||||
ymax = (VX(p0, y) > VX(p1, y)) ? VX(p0, y) : VX(p1, y);
|
||||
if (ymax < VX(p2, y))
|
||||
ymax = VX(p2, y);
|
||||
|
||||
for (init = 1, t0 = p2->next; t0 != p0; t0 = t0->next) {
|
||||
if (VX(t0, x) >= xmin && VX(t0, x) <= xmax &&
|
||||
VX(t0, y) >= ymin && VX(t0, y) <= ymax) {
|
||||
if (init) {
|
||||
a[1] = VX(p2, y) - VX(p0, y);
|
||||
b[1] = VX(p0, x) - VX(p2, x);
|
||||
init = 0;
|
||||
c[0] = VX(p1, x) * VX(p2, y) - VX(p2, x) * VX(p1, y);
|
||||
c[1] = VX(p2, x) * VX(p0, y) - VX(p0, x) * VX(p2, y);
|
||||
c[2] = VX(p0, x) * VX(p1, y) - VX(p1, x) * VX(p0, y);
|
||||
}
|
||||
|
||||
s[0] = a[0] * VX(t0, x) + b[0] * VX(t0, y) + c[0];
|
||||
s[1] = a[1] * VX(t0, x) + b[1] * VX(t0, y) + c[1];
|
||||
s[2] = a[2] * VX(t0, x) + b[2] * VX(t0, y) + c[2];
|
||||
|
||||
if (asum) {
|
||||
if (s[0] >= 0.0 && s[1] >= 0.0 && s[2] >= 0.0)
|
||||
break;
|
||||
} else {
|
||||
if (s[0] <= 0.0 && s[1] <= 0.0 && s[2] <= 0.0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (t0 != p0) {
|
||||
p0 = p1;
|
||||
p1 = p2;
|
||||
p2 = p2->next;
|
||||
} else {
|
||||
PrimType new_prim(prim);
|
||||
new_prim.set_type(BPT_tri);
|
||||
new_prim.clear_vertices();
|
||||
new_prim.add_vertex(prim.get_vertex(p0->index));
|
||||
new_prim.add_vertex(prim.get_vertex(p1->index));
|
||||
new_prim.add_vertex(prim.get_vertex(p2->index));
|
||||
output_prims.push_back(new_prim);
|
||||
|
||||
p0->next = p1->next;
|
||||
p1 = p2;
|
||||
p2 = p2->next;
|
||||
|
||||
m[0] = p0;
|
||||
m[1] = p1;
|
||||
m[2] = p2;
|
||||
chek = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PrimType new_prim(prim);
|
||||
new_prim.set_type(BPT_tri);
|
||||
new_prim.clear_vertices();
|
||||
new_prim.add_vertex(prim.get_vertex(p0->index));
|
||||
new_prim.add_vertex(prim.get_vertex(p1->index));
|
||||
new_prim.add_vertex(prim.get_vertex(p2->index));
|
||||
output_prims.push_back(new_prim);
|
||||
|
||||
copy(output_prims.begin(), output_prims.end(), result);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: triangulate_poly
|
||||
// Description: Breaks a (possibly concave) higher-order polygon into
|
||||
// a series of constituent triangles.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType, class OutputIterator>
|
||||
static bool
|
||||
triangulate_poly(const PrimType &prim, BuilderBucket &bucket,
|
||||
OutputIterator result) {
|
||||
BuilderV p0, p1, as;
|
||||
float dx1, dy1, dx2, dy2, max;
|
||||
int i, flag, asum, csum, index, x, y, v0, v1, v, even;
|
||||
|
||||
// First see if the polygon is just a triangle
|
||||
int num_verts = prim.get_num_verts();
|
||||
if (num_verts == 3) {
|
||||
PrimType new_prim(prim);
|
||||
new_prim.set_type(BPT_tri);
|
||||
*result++ = new_prim;
|
||||
|
||||
return true;
|
||||
|
||||
} else if (num_verts < 3) {
|
||||
// Or if it's a degenerate polygon.
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate signed areas
|
||||
as[0] = 0.0;
|
||||
as[1] = 0.0;
|
||||
as[2] = 0.0;
|
||||
|
||||
for (i = 0; i < num_verts; i++) {
|
||||
p0 = prim.get_vertex(i).get_coord_value(bucket);
|
||||
p1 = prim.get_vertex((i + 1) % num_verts).get_coord_value(bucket);
|
||||
as[0] += p0[0] * p1[1] - p0[1] * p1[0];
|
||||
as[1] += p0[0] * p1[2] - p0[2] * p1[0];
|
||||
as[2] += p0[1] * p1[2] - p0[2] * p1[1];
|
||||
}
|
||||
|
||||
/* select largest signed area */
|
||||
max = 0.0;
|
||||
index = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (as[i] >= 0.0) {
|
||||
if (as[i] > max) {
|
||||
max = as[i];
|
||||
index = i;
|
||||
flag = 1;
|
||||
}
|
||||
} else {
|
||||
as[i] = -as[i];
|
||||
if (as[i] > max) {
|
||||
max = as[i];
|
||||
index = i;
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* pointer offsets */
|
||||
switch (index) {
|
||||
case 0:
|
||||
x = 0;
|
||||
y = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
x = 0;
|
||||
y = 2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
x = 1;
|
||||
y = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* concave check */
|
||||
p0 = prim.get_vertex(0).get_coord_value(bucket);
|
||||
p1 = prim.get_vertex(1).get_coord_value(bucket);
|
||||
dx1 = p1[x] - p0[x];
|
||||
dy1 = p1[y] - p0[y];
|
||||
p0 = p1;
|
||||
p1 = prim.get_vertex(2).get_coord_value(bucket);
|
||||
|
||||
dx2 = p1[x] - p0[x];
|
||||
dy2 = p1[y] - p0[y];
|
||||
asum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
|
||||
|
||||
for (i = 0; i < num_verts - 1; i++) {
|
||||
p0 = p1;
|
||||
p1 = prim.get_vertex((i+3) % num_verts).get_coord_value(bucket);
|
||||
|
||||
dx1 = dx2;
|
||||
dy1 = dy2;
|
||||
dx2 = p1[x] - p0[x];
|
||||
dy2 = p1[y] - p0[y];
|
||||
csum = ((dx1 * dy2 - dx2 * dy1 >= 0.0) ? 1 : 0);
|
||||
|
||||
if (csum ^ asum) {
|
||||
return decomp_concave(prim, bucket, result, flag, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
v0 = 0;
|
||||
v1 = 1;
|
||||
v = num_verts - 1;
|
||||
|
||||
even = 1;
|
||||
|
||||
/*
|
||||
* Convert to triangles only. Do not fan out from a single vertex
|
||||
* but zigzag into triangle strip.
|
||||
*/
|
||||
for (i = 0; i < num_verts - 2; i++) {
|
||||
if (even) {
|
||||
PrimType new_prim(prim);
|
||||
new_prim.set_type(BPT_tri);
|
||||
new_prim.clear_vertices();
|
||||
new_prim.add_vertex(prim.get_vertex(v0));
|
||||
new_prim.add_vertex(prim.get_vertex(v1));
|
||||
new_prim.add_vertex(prim.get_vertex(v));
|
||||
*result++ = new_prim;
|
||||
v0 = v1;
|
||||
v1 = v;
|
||||
v = v0 + 1;
|
||||
} else {
|
||||
PrimType new_prim(prim);
|
||||
new_prim.set_type(BPT_tri);
|
||||
new_prim.clear_vertices();
|
||||
new_prim.add_vertex(prim.get_vertex(v1));
|
||||
new_prim.add_vertex(prim.get_vertex(v0));
|
||||
new_prim.add_vertex(prim.get_vertex(v));
|
||||
*result++ = new_prim;
|
||||
v0 = v1;
|
||||
v1 = v;
|
||||
v = v0 - 1;
|
||||
}
|
||||
|
||||
even = !even;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: expand_polys
|
||||
// Description: Identifies a single polygon as a triangle, quad, or
|
||||
// higher-order polygon, and writes it into the result
|
||||
// list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType, class OutputIterator>
|
||||
static bool
|
||||
expand_polys(PrimType &prim, BuilderBucket &,
|
||||
OutputIterator result) {
|
||||
switch (prim.get_num_verts()) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return false;
|
||||
|
||||
case 3:
|
||||
prim.set_type(BPT_tri);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
prim.set_type(BPT_quad);
|
||||
break;
|
||||
|
||||
default:
|
||||
prim.set_type(BPT_poly);
|
||||
}
|
||||
|
||||
*result++ = prim;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: expand_points
|
||||
// Description: Expands a light points primitive into its individual
|
||||
// component points, with one point per primitive.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType, class OutputIterator>
|
||||
static bool
|
||||
expand_points(const PrimType &prim, BuilderBucket &,
|
||||
OutputIterator result) {
|
||||
// Each vertex goes in its own primitive.
|
||||
|
||||
int num_verts = prim.get_num_verts();
|
||||
for (int i = 0; i < num_verts; i++) {
|
||||
PrimType new_prim(prim);
|
||||
new_prim.clear_vertices();
|
||||
new_prim.add_vertex(prim.get_vertex(i));
|
||||
*result++ = new_prim;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: expand_lines
|
||||
// Description: Expands a linestrip primitive into its component line
|
||||
// primitives.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType, class OutputIterator>
|
||||
static bool
|
||||
expand_lines(const PrimType &prim, BuilderBucket &,
|
||||
OutputIterator result) {
|
||||
// Each line segment goes in its own primitive. This breaks up the
|
||||
// linestrips already defined; we'll re-strip them later if the
|
||||
// generate-tstrips flag is enabled.
|
||||
|
||||
int num_verts = prim.get_num_verts();
|
||||
for (int i = 1; i < num_verts; i++) {
|
||||
PrimType new_prim(prim);
|
||||
new_prim.clear_vertices();
|
||||
new_prim.add_vertex(prim.get_vertex(i-1));
|
||||
new_prim.add_vertex(prim.get_vertex(i));
|
||||
*result++ = new_prim;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: expand
|
||||
// Description: Receives a single primitive as a BuilderPrim or
|
||||
// BuilderPrimI object, as input by the user. Does some
|
||||
// initial processing on the primitive to verify
|
||||
// internal consistency (for instance, that a quad has
|
||||
// four vertices), and returns a new BuilderPrim or
|
||||
// series of BuilderPrim objects, suitable for building
|
||||
// with.
|
||||
//
|
||||
// More than one primitive might be returned because
|
||||
// higher-order polygons may be broken up into
|
||||
// triangles, and linestrips and points are broken into
|
||||
// their component pieces. The output primitives are
|
||||
// written into the STL container defined by result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType, class OutputIterator>
|
||||
bool
|
||||
expand(const PrimType &prim, BuilderBucket &bucket, OutputIterator result) {
|
||||
// Make a copy of the prim so we can fiddle with it.
|
||||
PrimType new_prim = prim;
|
||||
|
||||
switch (new_prim.get_type()) {
|
||||
case BPT_poly:
|
||||
case BPT_tri:
|
||||
case BPT_quad:
|
||||
// These three types are all treated the same, as polygons. We
|
||||
// don't entirely trust the user to match the polygon type with
|
||||
// the number of verts, so we'll do it ourselves later.
|
||||
new_prim.remove_doubled_verts(true);
|
||||
|
||||
if (!bucket._subdivide_polys ||
|
||||
(bucket._mesh && new_prim.get_num_verts() <= 4)) {
|
||||
// If we're meshing, we'd like to send quads through without
|
||||
// subdividing. The mesher can take advantage of the extra
|
||||
// information (and will eventually produce tris anyway).
|
||||
return expand_polys(new_prim, bucket, result);
|
||||
} else {
|
||||
// If we're not meshing, we'll break them into tris now.
|
||||
return triangulate_poly(new_prim, bucket, result);
|
||||
}
|
||||
|
||||
case BPT_point:
|
||||
new_prim.remove_doubled_verts(false);
|
||||
return expand_points(new_prim, bucket, result);
|
||||
|
||||
case BPT_line:
|
||||
new_prim.remove_doubled_verts(false);
|
||||
return expand_lines(new_prim, bucket, result);
|
||||
|
||||
default:
|
||||
builder_cat.error() << "Unknown prim type\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: build_geoms
|
||||
// Description: Accepts a list of BuilderPrim or BuilderPrimI
|
||||
// objects, defined by the iterators first and last, and
|
||||
// creates corresponding geometry for them in the
|
||||
// indicated GeomNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class InputIterator, class PrimType>
|
||||
static int
|
||||
build_geoms(InputIterator first, InputIterator last,
|
||||
BuilderBucket &bucket, GeomNode *geom_node,
|
||||
PrimType *) {
|
||||
if (first==last) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// By the time we get here, we have a list of primitives that all have
|
||||
// the same properties:
|
||||
|
||||
// 1. The BuilderBucket.
|
||||
// 2. The indexed/nonindexed type.
|
||||
// 3. The primitive type (polygon, line, point).
|
||||
// 4. The pixel size.
|
||||
|
||||
// The binding of normals, colors, or texcoords: per-vertex,
|
||||
// per-prim, or per-component, will generally be the same across all
|
||||
// primitives, but it might not always be the same, because in
|
||||
// certain special cases the mesher might have changed these
|
||||
// properties when it built tristrips.
|
||||
|
||||
typedef TYPENAME PrimType::VType VType;
|
||||
typedef TYPENAME PrimType::NType NType;
|
||||
typedef TYPENAME PrimType::TType TType;
|
||||
typedef TYPENAME PrimType::CType CType;
|
||||
|
||||
// We need to determine the common binding type for all primitives.
|
||||
// For a given attribute, say normals, there are at most five cases,
|
||||
// in the order of priority:
|
||||
//
|
||||
// 1. If at least one primitive in the list does not have normals,
|
||||
// the binding will be G_OFF.
|
||||
//
|
||||
// 2. If at least one primitive has per-vertex normals, the binding
|
||||
// will be G_PER_VERTEX.
|
||||
//
|
||||
// 3. If at least one primitive has per-component normals, the
|
||||
// binding will be G_PER_COMPONENT.
|
||||
//
|
||||
// 4. If none of the first three apply, it follows that all
|
||||
// primitives have an overall normal. If any primitive's
|
||||
// overall normal differs from any other, the binding will be
|
||||
// G_PER_PRIM.
|
||||
//
|
||||
// 5. If none of the above apply, the binding will be G_OVERALL.
|
||||
//
|
||||
// An exception to the above is for texcoords, which is either G_OFF
|
||||
// (by rule 1) or G_PER_VERTEX.
|
||||
|
||||
GeomBindType bind_normals = G_OVERALL;
|
||||
GeomBindType bind_colors = G_OVERALL;
|
||||
GeomBindType bind_texcoords = G_PER_VERTEX;
|
||||
|
||||
NType overall_normal;
|
||||
CType overall_color;
|
||||
bool first_normal = true;
|
||||
bool first_color = true;
|
||||
|
||||
InputIterator i;
|
||||
for (i = first; i != last; ++i) {
|
||||
|
||||
// Normals.
|
||||
|
||||
// Test rule 1.
|
||||
if (!(*i).has_any_normal()) {
|
||||
bind_normals = G_OFF;
|
||||
} else if (bind_normals != G_OFF) {
|
||||
// Test rule 2.
|
||||
if ((*i).has_vertex_normal()) {
|
||||
bind_normals = G_PER_VERTEX;
|
||||
} else if (bind_normals != G_PER_VERTEX) {
|
||||
// Test rule 3.
|
||||
if ((*i).has_component_normal()) {
|
||||
bind_normals = G_PER_COMPONENT;
|
||||
} else if (bind_normals != G_PER_COMPONENT) {
|
||||
// Test rule 4.
|
||||
nassertr((*i).has_overall_normal(), 0);
|
||||
if (first_normal) {
|
||||
overall_normal = (*i).get_normal();
|
||||
first_normal = false;
|
||||
} else if ( !((*i).get_normal() == overall_normal)) {
|
||||
bind_normals = G_PER_PRIM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Colors.
|
||||
|
||||
// Test rule 1.
|
||||
if (!(*i).has_any_color()) {
|
||||
bind_colors = G_OFF;
|
||||
} else if (bind_colors != G_OFF) {
|
||||
// Test rule 2.
|
||||
if ((*i).has_vertex_color()) {
|
||||
bind_colors = G_PER_VERTEX;
|
||||
} else if (bind_colors != G_PER_VERTEX) {
|
||||
// Test rule 3.
|
||||
if ((*i).has_component_color()) {
|
||||
bind_colors = G_PER_COMPONENT;
|
||||
} else if (bind_colors != G_PER_COMPONENT) {
|
||||
// Test rule 4.
|
||||
nassertr((*i).has_overall_color(), 0);
|
||||
if (first_color) {
|
||||
overall_color = (*i).get_color();
|
||||
first_color = false;
|
||||
} else if ( !((*i).get_color() == overall_color)) {
|
||||
bind_colors = G_PER_PRIM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Texcoords.
|
||||
|
||||
// Test rule 1.
|
||||
if (!(*i).has_any_texcoord()) {
|
||||
bind_texcoords = G_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the primitive type and build the lengths array, if needed.
|
||||
PTA_int lengths;
|
||||
bool want_lengths = false;
|
||||
int j;
|
||||
|
||||
Geom *geom = NULL;
|
||||
BuilderPrimType type = (*first).get_type();
|
||||
switch (type) {
|
||||
case BPT_poly:
|
||||
geom = new GeomPolygon;
|
||||
want_lengths = true;
|
||||
break;
|
||||
|
||||
case BPT_tristrip:
|
||||
geom = new GeomTristrip;
|
||||
want_lengths = true;
|
||||
break;
|
||||
|
||||
case BPT_trifan:
|
||||
geom = new GeomTrifan;
|
||||
want_lengths = true;
|
||||
break;
|
||||
|
||||
case BPT_line:
|
||||
geom = new GeomLine;
|
||||
break;
|
||||
|
||||
case BPT_point:
|
||||
geom = new GeomPoint;
|
||||
break;
|
||||
|
||||
case BPT_tri:
|
||||
geom = new GeomTri;
|
||||
break;
|
||||
|
||||
case BPT_quad:
|
||||
geom = new GeomQuad;
|
||||
break;
|
||||
|
||||
default:
|
||||
builder_cat.fatal() << "Invalid primitive type.\n";
|
||||
abort();
|
||||
}
|
||||
|
||||
if (geom == NULL) {
|
||||
builder_cat.error() << "Unsupported primitive type " << type << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Count up the number of prims we're actually building.
|
||||
int num_prims = 0;
|
||||
for (i = first; i != last; ++i) {
|
||||
if ((*i).is_valid()) {
|
||||
num_prims++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_prims==0) {
|
||||
builder_cat.error() << "All primitives were invalid!\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (want_lengths) {
|
||||
lengths = PTA_int(num_prims);
|
||||
j = 0;
|
||||
for (i = first; i != last; ++i) {
|
||||
if ((*i).is_valid()) {
|
||||
lengths[j++] = (*i).get_num_verts();
|
||||
}
|
||||
}
|
||||
nassertr(j == num_prims, 0);
|
||||
}
|
||||
|
||||
// Now build up some arrays.
|
||||
PTA(VType) coords(0);
|
||||
PTA(NType) normals(0);
|
||||
PTA(TType) texcoords(0);
|
||||
PTA(CType) colors(0);
|
||||
|
||||
int total_verts = 0;
|
||||
int total_components = 0;
|
||||
|
||||
int v, num_verts;
|
||||
int c, num_components;
|
||||
for (i = first; i != last; ++i) {
|
||||
if ((*i).is_valid()) {
|
||||
num_verts = (*i).get_num_verts();
|
||||
total_verts += num_verts;
|
||||
for (v = 0; v < num_verts; v++) {
|
||||
coords.push_back((*i).get_vertex(v).get_coord());
|
||||
|
||||
if (bind_normals == G_PER_VERTEX) {
|
||||
normals.push_back((*i).get_vertex(v).get_normal());
|
||||
}
|
||||
if (bind_texcoords == G_PER_VERTEX) {
|
||||
texcoords.push_back((*i).get_vertex(v).get_texcoord());
|
||||
}
|
||||
if (bind_colors == G_PER_VERTEX) {
|
||||
colors.push_back((*i).get_vertex(v).get_color());
|
||||
}
|
||||
}
|
||||
|
||||
num_components = (*i).get_num_components();
|
||||
total_components += num_components;
|
||||
for (c = 0; c < num_components; c++) {
|
||||
if (bind_normals == G_PER_COMPONENT) {
|
||||
normals.push_back((*i).get_component(c).get_normal());
|
||||
}
|
||||
if (bind_colors == G_PER_COMPONENT) {
|
||||
colors.push_back((*i).get_component(c).get_color());
|
||||
}
|
||||
}
|
||||
|
||||
if (bind_normals == G_PER_PRIM) {
|
||||
normals.push_back((*i).get_normal());
|
||||
}
|
||||
if (bind_colors == G_PER_PRIM) {
|
||||
colors.push_back((*i).get_color());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bind_normals == G_OVERALL) {
|
||||
normals.push_back(overall_normal);
|
||||
}
|
||||
if (bind_colors == G_OVERALL) {
|
||||
colors.push_back(overall_color);
|
||||
}
|
||||
|
||||
// Now add all the stuff to our Geom.
|
||||
|
||||
geom->set_num_prims(num_prims);
|
||||
|
||||
if (lengths != (int *)NULL) {
|
||||
geom->set_lengths(lengths);
|
||||
}
|
||||
|
||||
PrimType::fill_geom(geom, coords,
|
||||
bind_normals, normals,
|
||||
bind_texcoords, texcoords,
|
||||
bind_colors, colors,
|
||||
bucket, num_prims,
|
||||
total_components, total_verts);
|
||||
|
||||
/*
|
||||
if ((*first).has_pixel_size()) {
|
||||
// Again, we only have to test the first one in the list for a
|
||||
// pixel_size attribute. If this one has it, then they all have
|
||||
// the same value.
|
||||
geom->setPntSize((*first).get_pixel_size());
|
||||
geom->setLineWidth((*first).get_pixel_size());
|
||||
}
|
||||
*/
|
||||
|
||||
// geom->setGState((pfGeoState *)bucket.getGState());
|
||||
// geom->setDrawBin(bucket._drawBin);
|
||||
// geom->setDrawOrder(bucket._drawOrder);
|
||||
|
||||
Geom *new_geom = bucket.done_geom(geom);
|
||||
if (new_geom != (Geom *)NULL) {
|
||||
geom_node->add_geom(new_geom);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : PrimByType
|
||||
// Description : An STL function object to sort primitives in order by
|
||||
// type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class PrimType>
|
||||
class PrimByType {
|
||||
public:
|
||||
int operator () (const PrimType &p1, const PrimType &p2) const {
|
||||
return p1.get_type() < p2.get_type();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: __mesh_and_build
|
||||
// Description: The implementation of mesh_and_build(), below. This
|
||||
// extra function call is just to allow mesh_and_build()
|
||||
// to infer the PrimType (BuilderPrim or BuilderPrimI)
|
||||
// from the iterator's value type, and template on that.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class InputIterator, class PrimType>
|
||||
static int
|
||||
__mesh_and_build(InputIterator first, InputIterator last,
|
||||
BuilderBucket &bucket, GeomNode *geom_node,
|
||||
PrimType *) {
|
||||
if (first==last) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef vector<PrimType> Prims;
|
||||
Prims prims;
|
||||
BuilderBucket *local_bucket = NULL;
|
||||
BuilderBucket *bucket_ptr = &bucket;
|
||||
|
||||
if (bucket._mesh) {
|
||||
// Send all the prims through the mesher. First, make a copy of
|
||||
// the bucket so the mesher can modify it if it wants.
|
||||
local_bucket = bucket.make_copy();
|
||||
bucket_ptr = local_bucket;
|
||||
MesherTempl<PrimType> mesher(local_bucket);
|
||||
|
||||
for (InputIterator ii = first; ii != last; ++ii) {
|
||||
mesher.add_prim(*ii);
|
||||
}
|
||||
mesher.mesh();
|
||||
PrimType prim;
|
||||
prim = mesher.getPrim();
|
||||
while (prim.get_num_verts() > 0) {
|
||||
prims.push_back(prim);
|
||||
prim = mesher.getPrim();
|
||||
}
|
||||
|
||||
} else {
|
||||
// Send the prims through without meshing.
|
||||
copy(first, last, back_inserter(prims));
|
||||
}
|
||||
|
||||
// Now we have an array of prims which all share the same
|
||||
// properties, except possibly type. Sort them by type and send
|
||||
// them to build_geoms.
|
||||
sort(prims.begin(), prims.end(), PrimByType<PrimType>());
|
||||
|
||||
int count = 0;
|
||||
if (!prims.empty()) {
|
||||
Prims::iterator pi, last_pi;
|
||||
pi = prims.begin();
|
||||
last_pi = pi;
|
||||
for (++pi; pi != prims.end(); ++pi) {
|
||||
if ((*pi).get_type() != (*last_pi).get_type()) {
|
||||
count += build_geoms(last_pi, pi, *bucket_ptr, geom_node, (PrimType*)0);
|
||||
last_pi = pi;
|
||||
}
|
||||
}
|
||||
count += build_geoms(last_pi, pi, *bucket_ptr, geom_node, (PrimType*)0);
|
||||
}
|
||||
|
||||
if (local_bucket!=NULL) {
|
||||
delete local_bucket;
|
||||
}
|
||||
|
||||
// Finally, if the user so requested, create some visualization for
|
||||
// the normals.
|
||||
#ifdef SUPPORT_SHOW_NORMALS
|
||||
if (bucket._show_normals) {
|
||||
BuilderNormalVisualizer bnv(bucket);
|
||||
for (InputIterator ii = first; ii != last; ++ii) {
|
||||
bnv.add_prim(*ii);
|
||||
}
|
||||
bnv.show_normals(geom_node);
|
||||
}
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: mesh_and_build
|
||||
// Description: Accepts a list of BuilderPrim or BuilderPrimI
|
||||
// objects, defined by the iterators first and list,
|
||||
// runs them through the mesher if specified by the
|
||||
// bucket, and builds them into the indicated GeomNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class InputIterator, class value_type>
|
||||
int
|
||||
mesh_and_build(InputIterator first, InputIterator last,
|
||||
BuilderBucket &bucket, GeomNode *geom_node,
|
||||
value_type *value_type_ptr) {
|
||||
return __mesh_and_build(first, last, bucket, geom_node, value_type_ptr);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: split
|
||||
// Description: Splits an STL list into two other lists, according to
|
||||
// the return value from pred.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class InputIterator, class OutputIterator, class Predicate>
|
||||
OutputIterator split(InputIterator first, InputIterator last,
|
||||
OutputIterator true_result, OutputIterator false_result,
|
||||
Predicate pred) {
|
||||
while (first != last) {
|
||||
if (pred(*first)) {
|
||||
*true_result++ = *first++;
|
||||
} else {
|
||||
*false_result++ = *first++;
|
||||
}
|
||||
}
|
||||
return true_result;
|
||||
}
|
||||
|
||||
66
panda/src/builder/builderFuncs.h
Normal file
66
panda/src/builder/builderFuncs.h
Normal file
@@ -0,0 +1,66 @@
|
||||
// Filename: builderFuncs.h
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifndef BUILDERFUNCS_H
|
||||
#define BUILDERFUNCS_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
|
||||
class BuilderBucket;
|
||||
class GeomNode;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: expand
|
||||
// Description: Receives a single primitive as a BuilderPrim or
|
||||
// BuilderPrimI object, as input by the user. Does some
|
||||
// initial processing on the primitive to verify
|
||||
// internal consistency (for instance, that a quad has
|
||||
// four vertices), and returns a new BuilderPrim or
|
||||
// series of BuilderPrim objects, suitable for building
|
||||
// with.
|
||||
//
|
||||
// More than one primitive might be returned because
|
||||
// higher-order polygons may be broken up into
|
||||
// triangles, and linestrips and points are broken into
|
||||
// their component pieces. The output primitives are
|
||||
// written into the STL container defined by result.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType, class OutputIterator>
|
||||
bool
|
||||
expand(const PrimType &prim, BuilderBucket &bucket,
|
||||
OutputIterator result);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: mesh_and_build
|
||||
// Description: Accepts a list of BuilderPrim or BuilderPrimI
|
||||
// objects, defined by the iterators first and list,
|
||||
// runs them through the mesher if specified by the
|
||||
// bucket, and builds them into the indicated GeomNode.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class InputIterator>
|
||||
int
|
||||
mesh_and_build(InputIterator first, InputIterator last,
|
||||
BuilderBucket &bucket, GeomNode *geom_node);
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: split
|
||||
// Description: Splits an STL list into two other lists, according to
|
||||
// the return value from pred.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class InputIterator, class OutputIterator, class Predicate>
|
||||
OutputIterator split(InputIterator first, InputIterator last,
|
||||
OutputIterator true_result, OutputIterator false_result,
|
||||
Predicate pred);
|
||||
|
||||
#include "builderFuncs.I"
|
||||
|
||||
#endif
|
||||
37
panda/src/builder/builderMisc.cxx
Normal file
37
panda/src/builder/builderMisc.cxx
Normal file
@@ -0,0 +1,37 @@
|
||||
// Filename: builderMisc.cxx
|
||||
// Created by: drose (18Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderMisc.h"
|
||||
#include "builderTypes.h"
|
||||
|
||||
#include <luse.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: make_random_color
|
||||
// Description: Chooses a reasonable random color.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
make_random_color(Colorf &color) {
|
||||
LVector3f rgb;
|
||||
float len;
|
||||
do {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
rgb[i] = (double)rand() / (double)RAND_MAX;
|
||||
}
|
||||
len = length(rgb);
|
||||
|
||||
// Repeat until we have a color that's not too dark or too light.
|
||||
} while (len < .1 || len > 1.5);
|
||||
|
||||
#ifdef WIN32_VC
|
||||
color.set(rgb[0], rgb[1], rgb[2],
|
||||
0.25 + 0.75 * (double)rand() / (double)RAND_MAX);
|
||||
#else
|
||||
color.set(rgb[0], rgb[1], rgb[2],
|
||||
0.25 + 0.75 * (double)random() / (double)RAND_MAX);
|
||||
#endif
|
||||
}
|
||||
|
||||
18
panda/src/builder/builderMisc.h
Normal file
18
panda/src/builder/builderMisc.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// Filename: builderMisc.h
|
||||
// Created by: drose (18Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifndef BUILDERMISC_H
|
||||
#define BUILDERMISC_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <luse.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: make_random_color
|
||||
// Description: Chooses a reasonable random color.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void make_random_color(Colorf &color);
|
||||
|
||||
#endif
|
||||
11
panda/src/builder/builderNormalVisualizer.I
Normal file
11
panda/src/builder/builderNormalVisualizer.I
Normal file
@@ -0,0 +1,11 @@
|
||||
// Filename: builderNormalVisualizer.I
|
||||
// Created by: drose (08Sep99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
INLINE BuilderNormalVisualizer::
|
||||
BuilderNormalVisualizer(BuilderBucket &bucket) : _bucket(bucket) {
|
||||
_num_vertices = 0;
|
||||
_net_vertex._v.set(0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
65
panda/src/builder/builderNormalVisualizer.cxx
Normal file
65
panda/src/builder/builderNormalVisualizer.cxx
Normal file
@@ -0,0 +1,65 @@
|
||||
// Filename: builderNormalVisualizer.cxx
|
||||
// Created by: drose (08Sep99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef SUPPORT_SHOW_NORMALS
|
||||
|
||||
#include "builderNormalVisualizer.h"
|
||||
#include "builderFuncs.h"
|
||||
|
||||
void BuilderNormalVisualizer::
|
||||
add_prim(const BuilderPrim &prim) {
|
||||
if (prim.has_overall_normal()) {
|
||||
// Average up all the vertex values to get the primitive center.
|
||||
BuilderV net_vertex;
|
||||
net_vertex._v.set(0.0, 0.0, 0.0);
|
||||
int num_verts = prim.get_num_verts();
|
||||
for (int i = 0; i < num_verts; i++) {
|
||||
net_vertex._v += prim.get_vertex(i).get_coord();
|
||||
}
|
||||
net_vertex._v /= num_verts;
|
||||
add_normal(net_vertex, prim.get_normal());
|
||||
|
||||
} else if (prim.has_vertex_normal()) {
|
||||
// Each vertex gets its own normal.
|
||||
int num_verts = prim.get_num_verts();
|
||||
for (int i = 0; i < num_verts; i++) {
|
||||
add_normal(prim.get_vertex(i).get_coord(), prim.get_vertex(i).get_normal());
|
||||
}
|
||||
} else if (prim.has_component_normal()) {
|
||||
// Each component gets its own normal. We don't presently handle
|
||||
// this, as it should only happen when the user passes
|
||||
// already-meshed tristrips into the builder, an unusual
|
||||
// situation.
|
||||
}
|
||||
}
|
||||
|
||||
void BuilderNormalVisualizer::
|
||||
add_prim(const BuilderPrimI &prim) {
|
||||
BuilderPrim prim_ni;
|
||||
prim_ni.nonindexed_copy(prim, _bucket);
|
||||
add_prim(prim_ni);
|
||||
}
|
||||
|
||||
void BuilderNormalVisualizer::
|
||||
show_normals(GeomNode *node) {
|
||||
// Ok, now we've got a bunch of normals saved up; create some geometry.
|
||||
mesh_and_build(_lines.begin(), _lines.end(), _bucket, node, (BuilderPrim *)0);
|
||||
}
|
||||
|
||||
void BuilderNormalVisualizer::
|
||||
add_normal(const BuilderV ¢er, const BuilderN &normal) {
|
||||
BuilderV to = center._v + normal._v * _bucket._normal_scale;
|
||||
|
||||
BuilderPrim line;
|
||||
line.set_type(BPT_line);
|
||||
line.set_color(_bucket._normal_color);
|
||||
line.add_vertex(BuilderVertex(center));
|
||||
line.add_vertex(BuilderVertex(to));
|
||||
|
||||
_lines.push_back(line);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
51
panda/src/builder/builderNormalVisualizer.h
Normal file
51
panda/src/builder/builderNormalVisualizer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// Filename: builderNormalVisualizer.h
|
||||
// Created by: drose (08Sep99)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERNORMALVISUALIZER_H
|
||||
#define BUILDERNORMALVISUALIZER_H
|
||||
|
||||
#ifdef SUPPORT_SHOW_NORMALS
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderBucket.h"
|
||||
#include "builderAttrib.h"
|
||||
#include "builderVertex.h"
|
||||
#include "builderPrim.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderNormalVisualizer
|
||||
// Description : A useful class for collecting information about
|
||||
// vertices and their associated normals as geometry is
|
||||
// built, so that its normals may be visualized via
|
||||
// renderable geometry. This is activated by the
|
||||
// _show_normals flag in the BuilderProperties.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderNormalVisualizer {
|
||||
public:
|
||||
INLINE BuilderNormalVisualizer(BuilderBucket &bucket);
|
||||
|
||||
void add_prim(const BuilderPrim &prim);
|
||||
void add_prim(const BuilderPrimI &prim);
|
||||
|
||||
void show_normals(GeomNode *node);
|
||||
|
||||
private:
|
||||
void add_normal(const BuilderV ¢er, const BuilderN &normal);
|
||||
|
||||
BuilderBucket &_bucket;
|
||||
|
||||
BuilderV _net_vertex;
|
||||
int _num_vertices;
|
||||
vector<BuilderPrim> _lines;
|
||||
};
|
||||
|
||||
#include "builderNormalVisualizer.I"
|
||||
|
||||
#endif // SUPPORT_SHOW_NORMALS
|
||||
|
||||
#endif
|
||||
194
panda/src/builder/builderPrim.cxx
Normal file
194
panda/src/builder/builderPrim.cxx
Normal file
@@ -0,0 +1,194 @@
|
||||
// Filename: builderPrim.cxx
|
||||
// Created by: drose (10Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderPrim.h"
|
||||
|
||||
#include <geom.h>
|
||||
#include <notify.h>
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderPrim::nonindexed_copy
|
||||
// Access: Public
|
||||
// Description: Makes a nonindexed copy of the given indexed prim, by
|
||||
// looking up the current values of the indexed
|
||||
// coordinates in the given bucket.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
BuilderPrim &BuilderPrim::
|
||||
nonindexed_copy(const BuilderPrimTempl<BuilderVertexI> ©,
|
||||
const BuilderBucket &bucket) {
|
||||
clear();
|
||||
|
||||
set_type(copy.get_type());
|
||||
|
||||
if (copy.has_normal()) {
|
||||
nassertr(bucket.get_normals() != (Normalf *)NULL, *this);
|
||||
set_normal(bucket.get_normals()[copy.get_normal()]);
|
||||
}
|
||||
if (copy.has_color()) {
|
||||
nassertr(bucket.get_colors() != (Colorf *)NULL, *this);
|
||||
set_color(bucket.get_colors()[copy.get_color()]);
|
||||
}
|
||||
if (copy.has_pixel_size()) {
|
||||
set_pixel_size(copy.get_pixel_size());
|
||||
}
|
||||
|
||||
int num_verts = copy.get_num_verts();
|
||||
int i;
|
||||
for (i = 0; i < num_verts; i++) {
|
||||
const BuilderVertexI &cv = copy.get_vertex(i);
|
||||
BuilderVertex v;
|
||||
if (cv.has_coord()) {
|
||||
v.set_coord(cv.get_coord_value(bucket));
|
||||
}
|
||||
|
||||
if (cv.has_normal()) {
|
||||
v.set_normal(cv.get_normal_value(bucket));
|
||||
}
|
||||
|
||||
if (cv.has_texcoord()) {
|
||||
v.set_texcoord(cv.get_texcoord_value(bucket));
|
||||
}
|
||||
|
||||
if (cv.has_color()) {
|
||||
v.set_color(cv.get_color_value(bucket));
|
||||
}
|
||||
|
||||
if (cv.has_pixel_size()) {
|
||||
v.set_pixel_size(cv.get_pixel_size());
|
||||
}
|
||||
add_vertex(v);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderPrim::fill_geom
|
||||
// Access: Public
|
||||
// Description: Fills up the attribute values of a Geom with the
|
||||
// indicated arrays. This creates a nonindexed Geom.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BuilderPrim::
|
||||
fill_geom(Geom *geom, const PTA_BuilderV &v_array,
|
||||
GeomBindType n_attr, const PTA_BuilderN &n_array,
|
||||
GeomBindType t_attr, const PTA_BuilderTC &t_array,
|
||||
GeomBindType c_attr, const PTA_BuilderC &c_array,
|
||||
const BuilderBucket &, int, int, int) {
|
||||
|
||||
// WARNING! This is questionable practice. We have a
|
||||
// PTA_BuilderV etc.; since a BuilderV is just a proxy
|
||||
// to a Vertexf, we can get away with casting this to a
|
||||
// PTA_Vertexf.
|
||||
|
||||
geom->set_coords((PTA_Vertexf &)v_array, G_PER_VERTEX);
|
||||
|
||||
if (n_attr != G_OFF) {
|
||||
geom->set_normals((PTA_Normalf &)n_array, n_attr);
|
||||
}
|
||||
|
||||
if (t_attr != G_OFF) {
|
||||
geom->set_texcoords((PTA_TexCoordf &)t_array, t_attr);
|
||||
}
|
||||
|
||||
if (c_attr != G_OFF) {
|
||||
geom->set_colors((PTA_Colorf &)c_array, c_attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderPrimI::fill_geom
|
||||
// Access: Public
|
||||
// Description: Fills up the attribute values of a Geom with the
|
||||
// indicated arrays. This creates an indexed Geom.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BuilderPrimI::
|
||||
fill_geom(Geom *geom, const PTA_ushort &v_array,
|
||||
GeomBindType n_attr, PTA_ushort n_array,
|
||||
GeomBindType t_attr, PTA_ushort t_array,
|
||||
GeomBindType c_attr, PTA_ushort c_array,
|
||||
const BuilderBucket &bucket,
|
||||
int num_prims, int num_components, int num_verts) {
|
||||
PTA_Vertexf v_data = bucket.get_coords();
|
||||
PTA_Normalf n_data = bucket.get_normals();
|
||||
PTA_TexCoordf t_data = bucket.get_texcoords();
|
||||
PTA_Colorf c_data = bucket.get_colors();
|
||||
|
||||
// Make sure the data pointers are NULL if the attribute is off.
|
||||
if (n_attr == G_OFF) {
|
||||
n_data = NULL;
|
||||
n_array = NULL;
|
||||
}
|
||||
if (t_attr == G_OFF) {
|
||||
t_data = NULL;
|
||||
t_array = NULL;
|
||||
}
|
||||
if (c_attr == G_OFF) {
|
||||
c_data = NULL;
|
||||
c_array = NULL;
|
||||
}
|
||||
|
||||
int n_len =
|
||||
(n_attr==G_PER_VERTEX) ? num_verts :
|
||||
(n_attr==G_PER_COMPONENT) ? num_components :
|
||||
(n_attr==G_PER_PRIM) ? num_prims :
|
||||
(n_attr==G_OVERALL) ? 1 : 0;
|
||||
int t_len =
|
||||
(t_attr==G_PER_VERTEX) ? num_verts :
|
||||
(t_attr==G_PER_COMPONENT) ? num_components :
|
||||
(t_attr==G_PER_PRIM) ? num_prims :
|
||||
(t_attr==G_OVERALL) ? 1 : 0;
|
||||
int c_len =
|
||||
(c_attr==G_PER_VERTEX) ? num_verts :
|
||||
(c_attr==G_PER_COMPONENT) ? num_components :
|
||||
(c_attr==G_PER_PRIM) ? num_prims :
|
||||
(c_attr==G_OVERALL) ? 1 : 0;
|
||||
|
||||
// See if we can share some of the index lists.
|
||||
if (n_attr != G_OFF &&
|
||||
memcmp(v_array, n_array, sizeof(ushort) * n_len)==0) {
|
||||
n_array = v_array;
|
||||
}
|
||||
if (t_attr != G_OFF) {
|
||||
if (memcmp(v_array, t_array, sizeof(ushort) * t_len)==0) {
|
||||
t_array = v_array;
|
||||
} else if (t_len <= n_len &&
|
||||
memcmp(n_array, t_array, sizeof(ushort) * t_len)==0) {
|
||||
t_array = n_array;
|
||||
}
|
||||
}
|
||||
if (c_attr != G_OFF) {
|
||||
if (memcmp(v_array, c_array, sizeof(ushort) * c_len)==0) {
|
||||
c_array = v_array;
|
||||
} else if (c_len <= n_len &&
|
||||
memcmp(n_array, c_array, sizeof(ushort) * c_len)==0) {
|
||||
c_array = n_array;
|
||||
} else if (c_len <= t_len &&
|
||||
memcmp(t_array, c_array, sizeof(ushort) * c_len)==0) {
|
||||
c_array = t_array;
|
||||
}
|
||||
}
|
||||
|
||||
geom->set_coords(v_data, G_PER_VERTEX, v_array);
|
||||
|
||||
if (n_attr != G_OFF) {
|
||||
geom->set_normals(n_data, n_attr, n_array);
|
||||
}
|
||||
|
||||
if (t_attr != G_OFF) {
|
||||
geom->set_texcoords(t_data, t_attr, t_array);
|
||||
}
|
||||
|
||||
if (c_attr != G_OFF) {
|
||||
geom->set_colors(c_data, c_attr, c_array);
|
||||
}
|
||||
}
|
||||
|
||||
119
panda/src/builder/builderPrim.h
Normal file
119
panda/src/builder/builderPrim.h
Normal file
@@ -0,0 +1,119 @@
|
||||
// Filename: builderPrim.h
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERPRIM_H
|
||||
#define BUILDERPRIM_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BuilderPrim, BuilderPrimI
|
||||
//
|
||||
// The basic class for passing primitives (polygons, etc.) to the
|
||||
// builder. See the comments at the beginning of builder.h and
|
||||
// builderVertex.h.
|
||||
//
|
||||
// A BuilderPrim has a few attributes of its own--color and
|
||||
// normal--which are defined in builderAttrib.h (which it inherits
|
||||
// from). It also has a collection of vertices, represented as
|
||||
// BuilderVertex objects, each of which can have its own attributes as
|
||||
// well. Any additional attributes, such as texture, lighting, etc.,
|
||||
// are considered to be external to the primitive, and are defined in
|
||||
// the BuilderBucket object.
|
||||
//
|
||||
// BuilderPrimI is exactly like BuilderPrim, except that it represents
|
||||
// an indexed primitive. A BuilderPrimI keeps its collection of
|
||||
// vertices as BuilderVertexI's, which store their values as index
|
||||
// numbers into an array rather than as actual coordinate values. The
|
||||
// arrays themselves are stored in the BuilderBucket.
|
||||
//
|
||||
// In fact, BuilderPrim and BuilderPrimI are both instantiations of
|
||||
// the same template object, BuilderPrimTempl, with different vertex
|
||||
// types (BuilderVertex and BuilderVertexI, respectively).
|
||||
//
|
||||
// It is this templating that drives most of the code in this package.
|
||||
// A lot of stuff in the builder tool, and everything in the mesher
|
||||
// tool, is templated on the BuilderPrim type, so the same code is
|
||||
// used to support both indexed and nonindexed primitives.
|
||||
//
|
||||
//
|
||||
// In addition to storing the primitives--individual polygons,
|
||||
// generally--as passed in by user code, BuilderPrim objects can store
|
||||
// the compound primitives that might have been generated by the
|
||||
// mesher, like triangle strips. In this case, in addition to an
|
||||
// array of vertices, it has an array of component attributes, which
|
||||
// store the attributes specific to each individual component
|
||||
// (e.g. the normal of each triangle in a triangle strip).
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderPrimTempl.h"
|
||||
#include "builderBucket.h"
|
||||
#include "pta_BuilderV.h"
|
||||
#include "pta_BuilderN.h"
|
||||
#include "pta_BuilderTC.h"
|
||||
#include "pta_BuilderC.h"
|
||||
|
||||
#include <pta_ushort.h>
|
||||
#include <geom.h>
|
||||
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, BuilderPrimTempl<BuilderVertex>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, BuilderPrimTempl<BuilderVertexI>);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderPrim
|
||||
// Description : The basic class for passing nonindexed primitives
|
||||
// to the builder. See the comments at the the head of
|
||||
// this file, and in builder.h.
|
||||
//
|
||||
// Look in builderPrimTempl.h and builderAttribTempl.h
|
||||
// for most of the interface to BuilderPrim.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderPrim : public BuilderPrimTempl<BuilderVertex> {
|
||||
public:
|
||||
BuilderPrim() {}
|
||||
|
||||
BuilderPrim &nonindexed_copy(const BuilderPrimTempl<BuilderVertexI> ©,
|
||||
const BuilderBucket &bucket);
|
||||
|
||||
static void fill_geom(Geom *geom, const PTA_BuilderV &v_array,
|
||||
GeomBindType n_attr, const PTA_BuilderN &n_array,
|
||||
GeomBindType t_attr, const PTA_BuilderTC &t_array,
|
||||
GeomBindType c_attr, const PTA_BuilderC &c_array,
|
||||
const BuilderBucket &bucket,
|
||||
int num_prims, int num_components, int num_verts);
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderPrimI
|
||||
// Description : The basic class for passing indexed primitives
|
||||
// to the builder.
|
||||
//
|
||||
// Look in builderPrimTempl.h and builderAttribTempl.h
|
||||
// for most of the interface to BuilderPrimI.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderPrimI : public BuilderPrimTempl<BuilderVertexI> {
|
||||
public:
|
||||
BuilderPrimI() {}
|
||||
|
||||
static void fill_geom(Geom *geom, const PTA_ushort &v_array,
|
||||
GeomBindType n_attr, PTA_ushort n_array,
|
||||
GeomBindType t_attr, PTA_ushort t_array,
|
||||
GeomBindType c_attr, PTA_ushort c_array,
|
||||
const BuilderBucket &bucket,
|
||||
int num_prims, int num_components, int num_verts);
|
||||
};
|
||||
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1025
panda/src/builder/builderPrimTempl.I
Normal file
1025
panda/src/builder/builderPrimTempl.I
Normal file
File diff suppressed because it is too large
Load Diff
143
panda/src/builder/builderPrimTempl.h
Normal file
143
panda/src/builder/builderPrimTempl.h
Normal file
@@ -0,0 +1,143 @@
|
||||
// Filename: builderPrimTempl.h
|
||||
// Created by: drose (11Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERPRIMTEMPL_H
|
||||
#define BUILDERPRIMTEMPL_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderVertex.h"
|
||||
#include "builderAttrib.h"
|
||||
#include "builderTypes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderPrimTempl
|
||||
// Description : The main body of BuilderPrim and BuilderPrimI. This
|
||||
// is a template class on vertex type, which must be
|
||||
// either BuilderVertex or BuilderVertexI; these classes
|
||||
// are themselves template classes on vertex type,
|
||||
// texcoord type, color type, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VTX>
|
||||
class BuilderPrimTempl : public VTX::Attrib {
|
||||
public:
|
||||
typedef VTX Vertex;
|
||||
typedef TYPENAME VTX::VType VType;
|
||||
typedef TYPENAME VTX::NType NType;
|
||||
typedef TYPENAME VTX::TType TType;
|
||||
typedef TYPENAME VTX::CType CType;
|
||||
typedef TYPENAME VTX::Attrib DAttrib;
|
||||
|
||||
INLINE BuilderPrimTempl();
|
||||
INLINE BuilderPrimTempl(const BuilderPrimTempl ©);
|
||||
INLINE BuilderPrimTempl &operator = (const BuilderPrimTempl ©);
|
||||
|
||||
void remove_doubled_verts(int closed);
|
||||
bool is_valid() const;
|
||||
|
||||
// has_normal() etc. is true if the primitive has a normal, as
|
||||
// assigned by the user. This is unrelated to the vertices or
|
||||
// component primitives that may or may not also have normals.
|
||||
INLINE bool has_normal() const;
|
||||
INLINE bool has_color() const;
|
||||
INLINE bool has_pixel_size() const;
|
||||
|
||||
// The following has_* functions are based on information derived
|
||||
// from examining the vertices and the component primitives that
|
||||
// make up this primitive.
|
||||
|
||||
// has_overall_normal() etc. is true if the primitive has a single,
|
||||
// overall normal shared among all vertices and all component
|
||||
// primitives, or if its normal was assigned directly via
|
||||
// set_normal(). For a polygon, this is the polygon normal. For a
|
||||
// tristrip, this means all triangles share the same normal.
|
||||
INLINE bool has_overall_normal() const;
|
||||
INLINE bool has_overall_color() const;
|
||||
INLINE bool has_overall_pixel_size() const;
|
||||
|
||||
// has_vertex_normal() etc. is true if each vertex in the primitive
|
||||
// has its own normal. It is not true if any vertex does not have a
|
||||
// normal.
|
||||
INLINE bool has_vertex_normal() const;
|
||||
INLINE bool has_vertex_color() const;
|
||||
INLINE bool has_vertex_texcoord() const;
|
||||
INLINE bool has_vertex_pixel_size() const;
|
||||
|
||||
// has_component_normal() can only be true for aggregate primitive
|
||||
// types like tristrips. In that case, it is true if each
|
||||
// individual component (e.g. each triangle of the tristrip) has its
|
||||
// own normal.
|
||||
INLINE bool has_component_normal() const;
|
||||
INLINE bool has_component_color() const;
|
||||
INLINE bool has_component_pixel_size() const;
|
||||
|
||||
// In the above, only one of has_overall_normal(),
|
||||
// has_vertex_normal(), and has_component_normal() can be true for a
|
||||
// given primitive. For convenience, the following functions return
|
||||
// true if any of the above is true:
|
||||
|
||||
INLINE bool has_any_normal() const;
|
||||
INLINE bool has_any_color() const;
|
||||
INLINE bool has_any_texcoord() const;
|
||||
INLINE bool has_any_pixel_size() const;
|
||||
|
||||
INLINE BuilderPrimTempl &clear();
|
||||
INLINE BuilderPrimTempl &clear_vertices();
|
||||
|
||||
INLINE BuilderPrimTempl &set_attrib(const DAttrib &attrib);
|
||||
|
||||
INLINE BuilderPrimType get_type() const;
|
||||
INLINE BuilderPrimTempl &set_type(BuilderPrimType t);
|
||||
|
||||
INLINE NType get_normal() const;
|
||||
INLINE BuilderPrimTempl &set_normal(const NType &n);
|
||||
|
||||
INLINE CType get_color() const;
|
||||
INLINE BuilderPrimTempl &set_color(const CType &c);
|
||||
|
||||
INLINE float get_pixel_size() const;
|
||||
INLINE BuilderPrimTempl &set_pixel_size(float s);
|
||||
|
||||
INLINE BuilderPrimTempl &add_vertex(const Vertex &v);
|
||||
|
||||
INLINE int get_num_verts() const;
|
||||
INLINE Vertex &get_vertex(int n);
|
||||
INLINE const Vertex &get_vertex(int n) const;
|
||||
|
||||
INLINE BuilderPrimTempl &add_component(const DAttrib &attrib);
|
||||
INLINE int get_num_components() const;
|
||||
INLINE DAttrib &get_component(int n);
|
||||
INLINE const DAttrib &get_component(int n) const;
|
||||
|
||||
INLINE bool operator < (const BuilderPrimTempl &other) const;
|
||||
|
||||
ostream &output(ostream &out) const;
|
||||
|
||||
protected:
|
||||
INLINE int sort_value() const;
|
||||
void update_overall_attrib();
|
||||
|
||||
typedef vector<Vertex> Verts;
|
||||
typedef vector<DAttrib> Components;
|
||||
|
||||
Verts _verts;
|
||||
Components _components;
|
||||
BuilderPrimType _type;
|
||||
int _overall;
|
||||
};
|
||||
|
||||
template <class VTX>
|
||||
INLINE ostream &operator << (ostream &out,
|
||||
const BuilderPrimTempl<VTX> &prim) {
|
||||
return prim.output(out);
|
||||
}
|
||||
|
||||
|
||||
#include "builderPrimTempl.I"
|
||||
|
||||
#endif
|
||||
116
panda/src/builder/builderProperties.cxx
Normal file
116
panda/src/builder/builderProperties.cxx
Normal file
@@ -0,0 +1,116 @@
|
||||
// Filename: builderProperties.cxx
|
||||
// Created by: drose (17Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderProperties.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderProperties::Ordering operator
|
||||
// Access: Public
|
||||
// Description: Defines an arbitrary ordering among different
|
||||
// properties, and groups identical sets of properties
|
||||
// together. This operator is used for the more
|
||||
// important task of grouping BuilderBuckets together;
|
||||
// see the comments for the similar function in
|
||||
// builderBucket.cxx.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BuilderProperties::
|
||||
operator < (const BuilderProperties &other) const {
|
||||
int sv1 = sort_value();
|
||||
int sv2 = other.sort_value();
|
||||
|
||||
if (sv1 != sv2) {
|
||||
return sv1 < sv2;
|
||||
}
|
||||
|
||||
if (_coplanar_threshold != other._coplanar_threshold) {
|
||||
return _coplanar_threshold < other._coplanar_threshold;
|
||||
}
|
||||
|
||||
if (_max_tfan_angle != other._max_tfan_angle) {
|
||||
return _max_tfan_angle < other._max_tfan_angle;
|
||||
}
|
||||
|
||||
if (_min_tfan_tris != other._min_tfan_tris) {
|
||||
return _min_tfan_tris < other._min_tfan_tris;
|
||||
}
|
||||
|
||||
if (_show_normals) {
|
||||
if (_normal_scale != other._normal_scale) {
|
||||
return _normal_scale < other._normal_scale;
|
||||
}
|
||||
if (_normal_color != other._normal_color) {
|
||||
return _normal_color < other._normal_color;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderPrimTempl::output
|
||||
// Access: Public
|
||||
// Description: Outputs the properties meaningfully.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BuilderProperties::
|
||||
output(ostream &out) const {
|
||||
if (_mesh) {
|
||||
out << "T-Mesh using Mesher\n";
|
||||
|
||||
if (_show_tstrips) {
|
||||
out << "Color individual tristrips\n";
|
||||
} else if (_show_qsheets) {
|
||||
out << "Color individual quadsheets\n";
|
||||
} else if (_show_quads) {
|
||||
out << "Color individual quads\n";
|
||||
}
|
||||
if (_retesselate_coplanar) {
|
||||
out << "Retesselate coplanar triangles when needed; threshold = "
|
||||
<< _coplanar_threshold << "\n";
|
||||
}
|
||||
}
|
||||
if (_subdivide_polys) {
|
||||
out << "Subdivide polygons into tris.\n";
|
||||
}
|
||||
if (_consider_fans) {
|
||||
out << "Look for possible triangle fans with max per-triangle angle of "
|
||||
<< _max_tfan_angle << " degrees.\n";
|
||||
if (_min_tfan_tris==0) {
|
||||
out << "Do not create tfans";
|
||||
} else {
|
||||
out << "Do not create tfans smaller than " << _min_tfan_tris << " tris";
|
||||
}
|
||||
if (_unroll_fans) {
|
||||
out << "; retesselate to tstrips.\n";
|
||||
} else {
|
||||
out << ".\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderPrimTempl::sort_value
|
||||
// Access: Protected
|
||||
// Description: Returns a number for grouping properties. This is
|
||||
// used as a helper function to the ordering operator,
|
||||
// above. It simply collects all the booleans together
|
||||
// into a single number.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BuilderProperties::
|
||||
sort_value() const {
|
||||
return
|
||||
((_mesh!=0) << 8) |
|
||||
((_show_tstrips!=0) << 7) |
|
||||
((_show_qsheets!=0) << 6) |
|
||||
((_show_quads!=0) << 5) |
|
||||
((_show_normals!=0) << 4) |
|
||||
((_retesselate_coplanar!=0) << 3) |
|
||||
((_unroll_fans!=0) << 2) |
|
||||
((_subdivide_polys!=0) << 1) |
|
||||
((_consider_fans!=0) << 0);
|
||||
}
|
||||
115
panda/src/builder/builderProperties.h
Normal file
115
panda/src/builder/builderProperties.h
Normal file
@@ -0,0 +1,115 @@
|
||||
// Filename: builderProperties.h
|
||||
// Created by: drose (17Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifndef BUILDERPROPERTIES_H
|
||||
#define BUILDERPROPERTIES_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderTypes.h"
|
||||
|
||||
#ifndef WIN32_VC
|
||||
#include <stl_config.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderProperties
|
||||
// Description : A class which defines several parameters used to
|
||||
// control specific behavior of the builder and mesher.
|
||||
// BuilderBucket inherits from this class, so each of
|
||||
// these properties may be set directly on a
|
||||
// BuilderBucket to control the geometry made with just
|
||||
// that bucket. There may in this way be several
|
||||
// different sets of properties in effect at a given
|
||||
// time.
|
||||
//
|
||||
// The initial values for these are set in the private
|
||||
// constructor to BuilderBucket, at the bottom of
|
||||
// builderBucket.cxx.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderProperties {
|
||||
public:
|
||||
bool operator < (const BuilderProperties &other) const;
|
||||
void output(ostream &out) const;
|
||||
|
||||
// If this is true, the mesher will be invoked to break up large
|
||||
// polygons and build triangles into tristrips wherever possible.
|
||||
bool _mesh;
|
||||
|
||||
// If this is true, a pair of adjacent coplanar triangles that form
|
||||
// a quad may be replaced with a pair of triangles forming the same
|
||||
// quad but with the opposite diagonal, if this will help the
|
||||
// building of tristrips.
|
||||
bool _retesselate_coplanar;
|
||||
|
||||
// If this is true, a coplanar fan may be treated as a single large
|
||||
// polygon, and then subdivided into a single tristrip, instead of
|
||||
// treating it as a fan. This can sometimes help form longer
|
||||
// continuous tristrips.
|
||||
bool _unroll_fans;
|
||||
|
||||
// The following three flags serve to illustrate the mesher's
|
||||
// effectiveness by coloring geometry.
|
||||
|
||||
// This colors each created triangle strip with a random color. The
|
||||
// first triangle of each strip is a little darker than the rest of
|
||||
// the strip.
|
||||
bool _show_tstrips;
|
||||
|
||||
// This colors each rectangular group of quads--called a quadsheet
|
||||
// by the mesher--with a random color. The mesher always creates
|
||||
// linear tristrips across whatever quadsheets it can identify.
|
||||
bool _show_qsheets;
|
||||
|
||||
// This colors quads blue, and doesn't mesh them further. Since a
|
||||
// large part of the mesher's algorithm is reassembling adjacent
|
||||
// triangles into quads, it's sometimes helpful to see where it
|
||||
// thinks the best quads lie.
|
||||
bool _show_quads;
|
||||
|
||||
// This shows normals created by creating little colored line
|
||||
// segments to represent each normal.
|
||||
bool _show_normals;
|
||||
double _normal_scale;
|
||||
BuilderC _normal_color;
|
||||
|
||||
// If this is true, large polygons will be subdivided into
|
||||
// triangles. Otherwise, they will remain large polygons.
|
||||
bool _subdivide_polys;
|
||||
|
||||
// This is the flatness tolerance below which two polygons will be
|
||||
// considered coplanar. Making it larger makes it easier for the
|
||||
// mesher to reverse triangle diagonals to achieve a good mesh, at
|
||||
// the expense of precision of the surface.
|
||||
double _coplanar_threshold;
|
||||
|
||||
// True if fans are to be considered at all. Sometimes making fans
|
||||
// is more trouble than they're worth, since they tend to get in the
|
||||
// way of long tristrips.
|
||||
bool _consider_fans;
|
||||
|
||||
// The maximum average angle of the apex of each triangle involved
|
||||
// in a fan. If the triangles are more loosely packed than this,
|
||||
// don't consider putting them into a fan.
|
||||
double _max_tfan_angle;
|
||||
|
||||
// The minimum number of triangles to be involved in a fan. Setting
|
||||
// this number lower results in more fans, probably at the expense
|
||||
// of tristrips. However, setting it to zero means no tfans will be
|
||||
// built (although fans may still be unrolled into tstrips if
|
||||
// _unroll_fans is true).
|
||||
int _min_tfan_tris;
|
||||
|
||||
protected:
|
||||
int sort_value() const;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const BuilderProperties &props) {
|
||||
props.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
102
panda/src/builder/builderTypes.cxx
Normal file
102
panda/src/builder/builderTypes.cxx
Normal file
@@ -0,0 +1,102 @@
|
||||
// Filename: builderTypes.cxx
|
||||
// Created by: drose (11Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderTypes.h"
|
||||
|
||||
#include <notify.h>
|
||||
|
||||
ostream &operator << (ostream &out, BuilderAttribFlags baf) {
|
||||
const char *space = "";
|
||||
if (baf & BAF_coord) {
|
||||
out << space << "coord";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_normal) {
|
||||
out << space << "normal";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_texcoord) {
|
||||
out << space << "texcoord";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_color) {
|
||||
out << space << "color";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_pixel_size) {
|
||||
out << space << "pixel_size";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_overall_updated) {
|
||||
out << space << "overall_updated";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_overall_normal) {
|
||||
out << space << "overall_normal";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_overall_color) {
|
||||
out << space << "overall_color";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_overall_pixel_size) {
|
||||
out << space << "overall_pixel_size";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_vertex_normal) {
|
||||
out << space << "vertex_normal";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_vertex_texcoord) {
|
||||
out << space << "vertex_texcoord";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_vertex_color) {
|
||||
out << space << "vertex_color";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_vertex_pixel_size) {
|
||||
out << space << "vertex_pixel_size";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_component_normal) {
|
||||
out << space << "component_normal";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_component_color) {
|
||||
out << space << "component_color";
|
||||
space = " ";
|
||||
}
|
||||
if (baf & BAF_component_pixel_size) {
|
||||
out << space << "component_pixel_size";
|
||||
space = " ";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
ostream &operator << (ostream &out, BuilderPrimType bpt) {
|
||||
switch (bpt) {
|
||||
case BPT_poly:
|
||||
return out << "poly";
|
||||
case BPT_point:
|
||||
return out << "point";
|
||||
case BPT_line:
|
||||
return out << "line";
|
||||
case BPT_tri:
|
||||
return out << "tri";
|
||||
case BPT_tristrip:
|
||||
return out << "tristrip";
|
||||
case BPT_trifan:
|
||||
return out << "trifan";
|
||||
case BPT_quad:
|
||||
return out << "quad";
|
||||
case BPT_quadstrip:
|
||||
return out << "quadstrip";
|
||||
}
|
||||
nassertr(false, out);
|
||||
return out << "(**invalid**)";
|
||||
}
|
||||
|
||||
221
panda/src/builder/builderTypes.h
Normal file
221
panda/src/builder/builderTypes.h
Normal file
@@ -0,0 +1,221 @@
|
||||
// Filename: builderTypes.h
|
||||
// Created by: drose (11Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifndef BUILDERTYPES_H
|
||||
#define BUILDERTYPES_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include <luse.h>
|
||||
#include <typedef.h>
|
||||
|
||||
#ifndef WIN32_VC
|
||||
#include <stl_config.h>
|
||||
#endif
|
||||
|
||||
static const float nearly_zero = 0.0001;
|
||||
|
||||
// The BuilderVec classes are a series of proxies around Vertexf,
|
||||
// Normalf, TexCoordf, and Colorf. They're useful for building
|
||||
// collections of these vertex values, and provide handy things like
|
||||
// (almost) equivalence operators and sorting operators.
|
||||
|
||||
// The BuilderVec's each have a special constructor with a single int.
|
||||
// These constructors create an instance of the vector with all values
|
||||
// initialized to zero. This is a cheat to create a uniform way to create
|
||||
// a zero-valued VType, CType, or TType without knowing whether the type
|
||||
// is indexed (a ushort) or nonindexed (a BuilderVec).
|
||||
|
||||
class EXPCL_PANDAEGG BuilderTC {
|
||||
public:
|
||||
BuilderTC() {}
|
||||
BuilderTC(int) : _v(0.0, 0.0) {}
|
||||
BuilderTC(const TexCoordf &v) : _v(v) {}
|
||||
BuilderTC(const TexCoordd &v) : _v(v[0], v[1]) {}
|
||||
BuilderTC(const BuilderTC ©) : _v(copy._v) {}
|
||||
|
||||
operator TexCoordf & () {
|
||||
return _v;
|
||||
}
|
||||
|
||||
operator const TexCoordf & () const {
|
||||
return _v;
|
||||
}
|
||||
|
||||
float operator [] (int n) const { return _v[n]; }
|
||||
float &operator [] (int n) { return _v[n]; }
|
||||
|
||||
BuilderTC &operator = (const BuilderTC ©) {
|
||||
_v = copy._v;
|
||||
return *this;
|
||||
}
|
||||
bool operator == (const BuilderTC &other) const {
|
||||
return _v.almost_equal(other._v, nearly_zero);
|
||||
}
|
||||
|
||||
// The < operator is simply for ordering vectors in a sorted
|
||||
// container; it has no useful mathematical meaning.
|
||||
bool operator < (const BuilderTC &other) const {
|
||||
return (_v.compare_to(other._v) < 0);
|
||||
}
|
||||
TexCoordf _v;
|
||||
};
|
||||
|
||||
class EXPCL_PANDAEGG BuilderV {
|
||||
public:
|
||||
BuilderV() {}
|
||||
BuilderV(int) : _v(0.0, 0.0, 0.0) {}
|
||||
BuilderV(const Vertexf &v) : _v(v) {}
|
||||
BuilderV(const Vertexd &v) : _v(v[0], v[1], v[2]) {}
|
||||
BuilderV(const BuilderV ©) : _v(copy._v) {}
|
||||
|
||||
operator Vertexf & () {
|
||||
return _v;
|
||||
}
|
||||
|
||||
operator const Vertexf & () const {
|
||||
return _v;
|
||||
}
|
||||
|
||||
float operator [] (int n) const { return _v[n]; }
|
||||
float &operator [] (int n) { return _v[n]; }
|
||||
|
||||
BuilderV &operator = (const BuilderV ©) {
|
||||
_v = copy._v;
|
||||
return *this;
|
||||
}
|
||||
bool operator == (const BuilderV &other) const {
|
||||
return _v.almost_equal(other._v, nearly_zero);
|
||||
}
|
||||
bool operator < (const BuilderV &other) const {
|
||||
return (_v.compare_to(other._v) < 0);
|
||||
}
|
||||
Vertexf _v;
|
||||
};
|
||||
|
||||
class EXPCL_PANDAEGG BuilderN {
|
||||
public:
|
||||
BuilderN() {}
|
||||
BuilderN(int) : _v(0.0, 0.0, 0.0) {}
|
||||
BuilderN(const Normalf &v) : _v(v) {}
|
||||
BuilderN(const Normald &v) : _v(v[0], v[1], v[2]) {}
|
||||
BuilderN(const BuilderN ©) : _v(copy._v) {}
|
||||
|
||||
operator Normalf & () {
|
||||
return _v;
|
||||
}
|
||||
|
||||
operator const Normalf & () const {
|
||||
return _v;
|
||||
}
|
||||
|
||||
float operator [] (int n) const { return _v[n]; }
|
||||
float &operator [] (int n) { return _v[n]; }
|
||||
|
||||
BuilderN &operator = (const BuilderN ©) {
|
||||
_v = copy._v;
|
||||
return *this;
|
||||
}
|
||||
bool operator == (const BuilderN &other) const {
|
||||
return _v.almost_equal(other._v, nearly_zero);
|
||||
}
|
||||
bool operator < (const BuilderN &other) const {
|
||||
return (_v.compare_to(other._v) < 0);
|
||||
}
|
||||
Normalf _v;
|
||||
};
|
||||
|
||||
class EXPCL_PANDAEGG BuilderC {
|
||||
public:
|
||||
BuilderC() {}
|
||||
BuilderC(int) : _v(0.0, 0.0, 0.0, 0.0) {}
|
||||
BuilderC(const Colorf &v) : _v(v) {}
|
||||
BuilderC(const Colord &v) : _v(v[0], v[1], v[2], v[3]) {}
|
||||
BuilderC(const BuilderC ©) : _v(copy._v) {}
|
||||
|
||||
operator Colorf & () {
|
||||
return _v;
|
||||
}
|
||||
|
||||
operator const Colorf & () const {
|
||||
return _v;
|
||||
}
|
||||
|
||||
float operator [] (int n) const { return _v[n]; }
|
||||
float &operator [] (int n) { return _v[n]; }
|
||||
|
||||
BuilderC &operator = (const BuilderC ©) {
|
||||
_v = copy._v;
|
||||
return *this;
|
||||
}
|
||||
bool operator != (const BuilderC &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
bool operator == (const BuilderC &other) const {
|
||||
return _v.almost_equal(other._v, nearly_zero);
|
||||
}
|
||||
bool operator < (const BuilderC &other) const {
|
||||
return (_v.compare_to(other._v) < 0);
|
||||
}
|
||||
Colorf _v;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const BuilderTC &v) {
|
||||
return out << "(" << v[0] << " " << v[1] << ")";
|
||||
}
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const BuilderV &v) {
|
||||
return out << "(" << v[0] << " " << v[1] << " " << v[2] << ")";
|
||||
}
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const BuilderN &v) {
|
||||
return out << "(" << v[0] << " " << v[1] << " " << v[2] << ")";
|
||||
}
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const BuilderC &v) {
|
||||
return out << "(" << v[0] << " " << v[1] << " " << v[2] << " "
|
||||
<< v[3] << ")";
|
||||
}
|
||||
|
||||
enum BuilderAttribFlags {
|
||||
BAF_coord = 0x00001,
|
||||
BAF_normal = 0x00002,
|
||||
BAF_texcoord = 0x00004,
|
||||
BAF_color = 0x00008,
|
||||
BAF_pixel_size = 0x00010,
|
||||
|
||||
BAF_overall_updated = 0x00100,
|
||||
BAF_overall_normal = 0x00200,
|
||||
BAF_overall_color = 0x00400,
|
||||
BAF_overall_pixel_size = 0x00800,
|
||||
|
||||
BAF_vertex_normal = 0x01000,
|
||||
BAF_vertex_texcoord = 0x02000,
|
||||
BAF_vertex_color = 0x04000,
|
||||
BAF_vertex_pixel_size = 0x08000,
|
||||
|
||||
BAF_component_normal = 0x10000,
|
||||
BAF_component_color = 0x20000,
|
||||
BAF_component_pixel_size = 0x04000,
|
||||
};
|
||||
|
||||
ostream &operator << (ostream &out, BuilderAttribFlags baf);
|
||||
|
||||
enum BuilderPrimType {
|
||||
BPT_poly,
|
||||
BPT_point,
|
||||
BPT_line,
|
||||
|
||||
// The following types are generated internally by the builder and
|
||||
// mesher. Normally they will not be seen by the user.
|
||||
BPT_tri,
|
||||
BPT_tristrip,
|
||||
BPT_trifan,
|
||||
BPT_quad,
|
||||
BPT_quadstrip,
|
||||
};
|
||||
|
||||
ostream &operator << (ostream &out, BuilderPrimType bpt);
|
||||
|
||||
#endif
|
||||
265
panda/src/builder/builderVertex.I
Normal file
265
panda/src/builder/builderVertex.I
Normal file
@@ -0,0 +1,265 @@
|
||||
// Filename: builderVertex.I
|
||||
// Created by: drose (18Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <notify.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_coord_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex coordinate, without knowing
|
||||
// whether the vertex is indexed or nonindexed. A
|
||||
// nonindexed vertex will look up the index in the array
|
||||
// and store the resulting value, while an indexed
|
||||
// vertex will just store the index number (which
|
||||
// assumes the array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertex::
|
||||
set_coord_value(const BuilderV *array, ushort index) {
|
||||
set_coord(array[index]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_normal_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex normal, without knowing whether
|
||||
// the vertex is indexed or nonindexed. A nonindexed
|
||||
// vertex will look up the index in the array and store
|
||||
// the resulting value, while an indexed vertex will
|
||||
// just store the index number (which assumes the array
|
||||
// is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertex::
|
||||
set_normal_value(const BuilderN *array, ushort index) {
|
||||
set_normal(array[index]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_texcoord_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex texture coordinate, without
|
||||
// knowing whether the vertex is indexed or nonindexed.
|
||||
// A nonindexed vertex will look up the index in the
|
||||
// array and store the resulting value, while an indexed
|
||||
// vertex will just store the index number (which
|
||||
// assumes the array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertex::
|
||||
set_texcoord_value(const BuilderTC *array, ushort index) {
|
||||
set_texcoord(array[index]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_color_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex color, without knowing whether
|
||||
// the vertex is indexed or nonindexed. A nonindexed
|
||||
// vertex will look up the index in the array and store
|
||||
// the resulting value, while an indexed vertex will
|
||||
// just store the index number (which assumes the array
|
||||
// is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertex::
|
||||
set_color_value(const BuilderC *array, ushort index) {
|
||||
set_color(array[index]);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_coord_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual coordinate value of the vertex,
|
||||
// whether it is indexed or nonindexed. Normally, the
|
||||
// value returned by get_coord(), which will be either a
|
||||
// BuilderV or a ushort, is sufficient, but there are
|
||||
// occasional times when it is necessary to get the
|
||||
// actual location in space of the vertex position (for
|
||||
// instance, to subdivide a concave polygon).
|
||||
//
|
||||
// This function returns the actual coordinate value.
|
||||
// For a nonindexed vertex, its return value is the same
|
||||
// as get_coord(); for an indexed vertex, it looks up
|
||||
// the vertex's index in the bucket's coord array, and
|
||||
// returns that value.
|
||||
//
|
||||
// Note that this makes some perhaps unwarranted
|
||||
// assumptions about indexed geometry; specifically,
|
||||
// that its value is valid at creation time, and that it
|
||||
// won't change too drastically during runtime.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderV BuilderVertex::
|
||||
get_coord_value(const BuilderBucket &) const {
|
||||
return get_coord();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_normal_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual normal value of the vertex,
|
||||
// whether it is indexed or nonindexed. See
|
||||
// get_coord_value().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderN BuilderVertex::
|
||||
get_normal_value(const BuilderBucket &) const {
|
||||
return get_normal();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_texcoord_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual texture coordinate value of the
|
||||
// vertex, whether it is indexed or nonindexed. See
|
||||
// get_coord_value().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderTC BuilderVertex::
|
||||
get_texcoord_value(const BuilderBucket &) const {
|
||||
return get_texcoord();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_color_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual color value of the vertex,
|
||||
// whether it is indexed or nonindexed. See
|
||||
// get_coord_value().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderC BuilderVertex::
|
||||
get_color_value(const BuilderBucket &) const {
|
||||
return get_color();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_coord_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex coordinate, without knowing
|
||||
// whether the vertex is indexed or nonindexed. A
|
||||
// nonindexed vertex will look up the index in the array
|
||||
// and store the resulting value, while an indexed
|
||||
// vertex will just store the index number (which
|
||||
// assumes the array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertexI::
|
||||
set_coord_value(const BuilderV *, ushort index) {
|
||||
set_coord(index);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_normal_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex normal, without knowing whether
|
||||
// the vertex is indexed or nonindexed. A nonindexed
|
||||
// vertex will look up the index in the array and store
|
||||
// the resulting value, while an indexed vertex will
|
||||
// just store the index number (which assumes the array
|
||||
// is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertexI::
|
||||
set_normal_value(const BuilderN *, ushort index) {
|
||||
set_normal(index);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_texcoord_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex texture coordinate, without
|
||||
// knowing whether the vertex is indexed or nonindexed.
|
||||
// A nonindexed vertex will look up the index in the
|
||||
// array and store the resulting value, while an indexed
|
||||
// vertex will just store the index number (which
|
||||
// assumes the array is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertexI::
|
||||
set_texcoord_value(const BuilderTC *, ushort index) {
|
||||
set_texcoord(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::set_color_value
|
||||
// Access: Public
|
||||
// Description: Reassigns the vertex color, without knowing whether
|
||||
// the vertex is indexed or nonindexed. A nonindexed
|
||||
// vertex will look up the index in the array and store
|
||||
// the resulting value, while an indexed vertex will
|
||||
// just store the index number (which assumes the array
|
||||
// is the same one it's indexing on).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void BuilderVertexI::
|
||||
set_color_value(const BuilderC *, ushort index) {
|
||||
set_color(index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_coord_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual coordinate value of the vertex,
|
||||
// whether it is indexed or nonindexed. Normally, the
|
||||
// value returned by get_coord(), which will be either a
|
||||
// BuilderV or a ushort, is sufficient, but there are
|
||||
// occasional times when it is necessary to get the
|
||||
// actual location in space of the vertex position (for
|
||||
// instance, to subdivide a concave polygon).
|
||||
//
|
||||
// This function returns the actual coordinate value.
|
||||
// For a nonindexed vertex, its return value is the same
|
||||
// as get_coord(); for an indexed vertex, it looks up
|
||||
// the vertex's index in the bucket's coord array, and
|
||||
// returns that value.
|
||||
//
|
||||
// Note that this makes some perhaps unwarranted
|
||||
// assumptions about indexed geometry; specifically,
|
||||
// that its value is valid at creation time, and that it
|
||||
// won't change too drastically during runtime.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderV BuilderVertexI::
|
||||
get_coord_value(const BuilderBucket &bucket) const {
|
||||
nassertr(bucket.get_coords() != (Vertexf *)NULL, BuilderV());
|
||||
return bucket.get_coords()[get_coord()];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_normal_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual normal value of the vertex,
|
||||
// whether it is indexed or nonindexed. See
|
||||
// get_coord_value().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderN BuilderVertexI::
|
||||
get_normal_value(const BuilderBucket &bucket) const {
|
||||
nassertr(bucket.get_normals() != (Normalf *)NULL, BuilderN());
|
||||
return bucket.get_normals()[get_normal()];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_texcoord_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual texture coordinate value of the
|
||||
// vertex, whether it is indexed or nonindexed. See
|
||||
// get_coord_value().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderTC BuilderVertexI::
|
||||
get_texcoord_value(const BuilderBucket &bucket) const {
|
||||
nassertr(bucket.get_texcoords() != (TexCoordf *)NULL, BuilderTC());
|
||||
return bucket.get_texcoords()[get_texcoord()];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertex::get_color_value
|
||||
// Access: Public
|
||||
// Description: Returns the actual color value of the vertex,
|
||||
// whether it is indexed or nonindexed. See
|
||||
// get_coord_value().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE BuilderC BuilderVertexI::
|
||||
get_color_value(const BuilderBucket &bucket) const {
|
||||
nassertr(bucket.get_colors() != (Colorf *)NULL, BuilderC());
|
||||
return bucket.get_colors()[get_color()];
|
||||
}
|
||||
12
panda/src/builder/builderVertex.cxx
Normal file
12
panda/src/builder/builderVertex.cxx
Normal file
@@ -0,0 +1,12 @@
|
||||
// Filename: builderVertex.cxx
|
||||
// Created by: drose (11May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderAttrib.h"
|
||||
#include "builderVertex.h"
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma implementation
|
||||
#endif
|
||||
119
panda/src/builder/builderVertex.h
Normal file
119
panda/src/builder/builderVertex.h
Normal file
@@ -0,0 +1,119 @@
|
||||
// Filename: builderVertex.h
|
||||
// Created by: drose (18Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERVERTEX_H
|
||||
#define BUILDERVERTEX_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BuilderVertex, BuilderVertexI
|
||||
//
|
||||
// The basic class for passing vertex values to the builder. See the
|
||||
// comments at the beginning of builder.h and builderPrim.h.
|
||||
//
|
||||
// Like BuilderPrim, the BuilderVertex and BuilderVertexI classes are
|
||||
// actually two different instantiations of the same template class,
|
||||
// BuilderVertexTempl. The difference is in the types of the
|
||||
// attribute values for the four kinds of attributes: vertices
|
||||
// (coords), normals, texture coordinates, and colors. BuilderVertex
|
||||
// specifies Coordf, Normalf, TexCoordf, and Colorf for each of these
|
||||
// (actually, it's BuilderV, BuilderN, BuilderTC, and BuilderC, which
|
||||
// are simply wrappers around the above types), while BuilderVertexI
|
||||
// specifies ushort for all of them.
|
||||
//
|
||||
// It is this templating that drives the whole indexed/nonindexed
|
||||
// support in this package and in the mesher. The two kinds of
|
||||
// BuilderVertex are designed to present largely the same interface,
|
||||
// regardless of whether its component values are actual vector
|
||||
// values, or simply index numbers. Lots of things, therefore, can
|
||||
// template on the BuilderPrim type (which in turn termplates on the
|
||||
// BuilderVertex type) and thus easily support both indexed and
|
||||
// nonindexed geometry.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderAttrib.h"
|
||||
#include "builderVertexTempl.h"
|
||||
#include "builderBucket.h"
|
||||
|
||||
// We need to define this temporary macro so we can pass a parameter
|
||||
// containing a comma through the macro.
|
||||
#define BUILDERVERTEXTEMPL_BUILDERV BuilderVertexTempl<BuilderV, BuilderN, BuilderTC, BuilderC>
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, BUILDERVERTEXTEMPL_BUILDERV);
|
||||
#define BUILDERVERTEXTEMPL_USHORT BuilderVertexTempl<ushort, ushort, ushort, ushort>
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, BUILDERVERTEXTEMPL_USHORT);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderVertex
|
||||
// Description : The basic class for passing nonindexed vertices to
|
||||
// the builder. See the comments at the the head of
|
||||
// this file, and in builder.h.
|
||||
//
|
||||
// Look in builderVertexTempl.h and builderAttribTempl.h
|
||||
// for most of the interface to BuilderVertex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderVertex
|
||||
: public BuilderVertexTempl<BuilderV, BuilderN, BuilderTC, BuilderC> {
|
||||
public:
|
||||
typedef BuilderAttrib Attrib;
|
||||
|
||||
BuilderVertex() {}
|
||||
BuilderVertex(const BuilderV &c) :
|
||||
BuilderVertexTempl<BuilderV, BuilderN, BuilderTC, BuilderC>(c) {}
|
||||
|
||||
INLINE void set_coord_value(const BuilderV *array, ushort index);
|
||||
INLINE void set_normal_value(const BuilderN *array, ushort index);
|
||||
INLINE void set_texcoord_value(const BuilderTC *array, ushort index);
|
||||
INLINE void set_color_value(const BuilderC *array, ushort index);
|
||||
|
||||
INLINE BuilderV get_coord_value(const BuilderBucket &bucket) const;
|
||||
INLINE BuilderN get_normal_value(const BuilderBucket &bucket) const;
|
||||
INLINE BuilderTC get_texcoord_value(const BuilderBucket &bucket) const;
|
||||
INLINE BuilderC get_color_value(const BuilderBucket &bucket) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderVertexI
|
||||
// Description : The basic class for passing indexed vertices to the
|
||||
// builder. See the comments at the the head of this
|
||||
// file, and in builder.h.
|
||||
//
|
||||
// Look in builderVertexTempl.h and builderAttribTempl.h
|
||||
// for most of the interface to BuilderVertex.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEGG BuilderVertexI
|
||||
: public BuilderVertexTempl<ushort, ushort, ushort, ushort> {
|
||||
public:
|
||||
typedef BuilderAttribI Attrib;
|
||||
|
||||
BuilderVertexI() {}
|
||||
BuilderVertexI(ushort c) :
|
||||
BuilderVertexTempl<ushort, ushort, ushort, ushort>(c) {}
|
||||
|
||||
INLINE void set_coord_value(const BuilderV *array, ushort index);
|
||||
INLINE void set_normal_value(const BuilderN *array, ushort index);
|
||||
INLINE void set_texcoord_value(const BuilderTC *array, ushort index);
|
||||
INLINE void set_color_value(const BuilderC *array, ushort index);
|
||||
|
||||
INLINE BuilderV get_coord_value(const BuilderBucket &bucket) const;
|
||||
INLINE BuilderN get_normal_value(const BuilderBucket &bucket) const;
|
||||
INLINE BuilderTC get_texcoord_value(const BuilderBucket &bucket) const;
|
||||
INLINE BuilderC get_color_value(const BuilderBucket &bucket) const;
|
||||
};
|
||||
|
||||
#include "builderVertex.I"
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
291
panda/src/builder/builderVertexTempl.I
Normal file
291
panda/src/builder/builderVertexTempl.I
Normal file
@@ -0,0 +1,291 @@
|
||||
// Filename: builderVertexTempl.I
|
||||
// Created by: drose (11Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <notify.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
BuilderVertexTempl() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::Constructor (with VType)
|
||||
// Access: Public
|
||||
// Description: Initializes the vertex coordinate with an initial
|
||||
// value. A handy constructor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
BuilderVertexTempl(const VType &c) {
|
||||
set_coord(c);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::Copy constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
BuilderVertexTempl(const BuilderVertexTempl ©) {
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::Copy assignment operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
operator = (const BuilderVertexTempl<VT, NT, TT, CT> ©) {
|
||||
BuilderAttribTempl<VT, NT, TT, CT>::operator = (copy);
|
||||
_coord = copy._coord;
|
||||
_texcoord = copy._texcoord;
|
||||
_pixel_size = copy._pixel_size;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::is_valid
|
||||
// Access: Public
|
||||
// Description: Returns true if the vertex is valid, i.e. if it has a
|
||||
// vertex coordinate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
is_valid() const {
|
||||
return has_coord();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::clear
|
||||
// Access: Public
|
||||
// Description: Resets the vertex to its initial, empty state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
clear() {
|
||||
BuilderAttribTempl<VT, NT, TT, CT>::clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::has_coord
|
||||
// Access: Public
|
||||
// Description: Returns true if the vertex has a vertex coordinate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
has_coord() const {
|
||||
return _flags & BAF_coord;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::get_coord
|
||||
// Access: Public
|
||||
// Description: Returns the vertex's coordinate. It is an error to
|
||||
// call this without first verifying that has_coord() is
|
||||
// true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT>::VType BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
get_coord() const {
|
||||
nassertr(has_coord(), _coord);
|
||||
return _coord;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::set_coord
|
||||
// Access: Public
|
||||
// Description: Resets the vertex's coordinate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
set_coord(const VType &c) {
|
||||
_flags |= BAF_coord;
|
||||
_coord = c;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::set_normal
|
||||
// Access: Public
|
||||
// Description: Resets the vertex's normal. This is overridden from
|
||||
// BuilderAttrib just so we can typecast the return
|
||||
// value to BuilderVertex. The other functions,
|
||||
// has_normal() and get_normal(), are inherited
|
||||
// untouched from BuilderAttrib.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
set_normal(const NType &n) {
|
||||
BuilderAttribTempl<VT, NT, TT, CT>::set_normal(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::has_texcoord
|
||||
// Access: Public
|
||||
// Description: Returns true if the vertex has a texture coordinate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE bool BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
has_texcoord() const {
|
||||
return (_flags & BAF_texcoord) != 0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::set_texcoord
|
||||
// Access: Public
|
||||
// Description: Resets the vertex's texture coordinate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
set_texcoord(const TType &t) {
|
||||
_flags |= BAF_texcoord;
|
||||
_texcoord = t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::get_texcoord
|
||||
// Access: Public
|
||||
// Description: Returns the vertex's texture coordinate. It is an
|
||||
// error to call this without first verifying that
|
||||
// has_texcoord() is true.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT>::TType BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
get_texcoord() const {
|
||||
nassertr(has_texcoord(), _texcoord);
|
||||
return _texcoord;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::set_color
|
||||
// Access: Public
|
||||
// Description: Resets the vertex's color. This is overridden from
|
||||
// BuilderAttrib just so we can typecast the return
|
||||
// value to BuilderVertex. The other functions,
|
||||
// has_color() and get_color(), are inherited
|
||||
// untouched from BuilderAttrib.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
set_color(const CType &c) {
|
||||
BuilderAttribTempl<VT, NT, TT, CT>::set_color(c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::set_pixel_size
|
||||
// Access: Public
|
||||
// Description: Resets the vertex's pixel_size. This is overridden
|
||||
// from BuilderAttrib just so we can typecast the return
|
||||
// value to BuilderVertex. The other functions,
|
||||
// has_pixel_size() and get_pixel_size(), are inherited
|
||||
// untouched from BuilderAttrib.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE BuilderVertexTempl<VT, NT, TT, CT> &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
set_pixel_size(float s) {
|
||||
BuilderAttribTempl<VT, NT, TT, CT>::set_pixel_size(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::operator ==
|
||||
// Access: Public
|
||||
// Description: Assigns an ordering to the vertices. This is used by
|
||||
// the Mesher to group identical vertices. This assumes
|
||||
// that all vertices in the locus of consideration will
|
||||
// share the same state: with or without normals,
|
||||
// texcoords, etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
bool BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
operator == (const BuilderVertexTempl<VT, NT, TT, CT> &other) const {
|
||||
if (has_coord() && !(_coord == other._coord))
|
||||
return false;
|
||||
|
||||
if (has_texcoord() && !(_texcoord == other._texcoord))
|
||||
return false;
|
||||
|
||||
return BuilderAttribTempl<VT, NT, TT, CT>::operator == (other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::operator <
|
||||
// Access: Public
|
||||
// Description: Assigns an ordering to the vertices. This is used by
|
||||
// the Mesher to group identical vertices. This assumes
|
||||
// that all vertices to be meshed together must share
|
||||
// the same state: with or without normals, texcoords,
|
||||
// etc.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
bool BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
operator < (const BuilderVertexTempl<VT, NT, TT, CT> &other) const {
|
||||
if (has_coord() && !(_coord == other._coord))
|
||||
return _coord < other._coord;
|
||||
|
||||
if (has_texcoord() && !(_texcoord == other._texcoord))
|
||||
return _texcoord < other._texcoord;
|
||||
|
||||
return BuilderAttribTempl<VT, NT, TT, CT>::operator < (other);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BuilderVertexTempl::output
|
||||
// Access: Public
|
||||
// Description: Formats the vertex for output in some sensible way.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
ostream &BuilderVertexTempl<VT, NT, TT, CT>::
|
||||
output(ostream &out) const {
|
||||
if (this!=NULL) {
|
||||
if (has_coord()) {
|
||||
out << get_coord();
|
||||
}
|
||||
|
||||
/*
|
||||
if (has_normal()) {
|
||||
out << " normal " << get_normal();
|
||||
}
|
||||
|
||||
if (has_texcoord()) {
|
||||
out << " texcoord " << get_texcoord();
|
||||
}
|
||||
|
||||
if (has_color()) {
|
||||
out << " color " << get_color();
|
||||
}
|
||||
|
||||
if (has_pixel_size()) {
|
||||
out << " pixel_size " << get_pixel_size();
|
||||
}
|
||||
*/
|
||||
}
|
||||
return out;
|
||||
}
|
||||
73
panda/src/builder/builderVertexTempl.h
Normal file
73
panda/src/builder/builderVertexTempl.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// Filename: builderVertexTempl.h
|
||||
// Created by: drose (09Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BUILDERVERTEXTEMPL_H
|
||||
#define BUILDERVERTEXTEMPL_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderTypes.h"
|
||||
#include "builderAttribTempl.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Class : BuilderVertexTempl
|
||||
// Description : The main body of BuilderVertex and BuilderVertexI.
|
||||
// This is a template class on each of the four
|
||||
// attribute types: vertex coordinates, normal, texture
|
||||
// coordinates, and color. See builderVertex.h.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
class BuilderVertexTempl : public BuilderAttribTempl<VT, NT, TT, CT> {
|
||||
public:
|
||||
typedef VT VType;
|
||||
typedef NT NType;
|
||||
typedef TT TType;
|
||||
typedef CT CType;
|
||||
|
||||
INLINE BuilderVertexTempl();
|
||||
INLINE BuilderVertexTempl(const VType &c);
|
||||
INLINE BuilderVertexTempl(const BuilderVertexTempl ©);
|
||||
INLINE BuilderVertexTempl &operator = (const BuilderVertexTempl ©);
|
||||
|
||||
INLINE bool is_valid() const;
|
||||
INLINE BuilderVertexTempl &clear();
|
||||
|
||||
INLINE bool has_coord() const;
|
||||
INLINE VType get_coord() const;
|
||||
INLINE BuilderVertexTempl &set_coord(const VType &c);
|
||||
|
||||
INLINE BuilderVertexTempl &set_normal(const NType &c);
|
||||
|
||||
INLINE bool has_texcoord() const;
|
||||
INLINE TType get_texcoord() const;
|
||||
INLINE BuilderVertexTempl &set_texcoord(const TType &t);
|
||||
|
||||
INLINE BuilderVertexTempl &set_color(const CType &c);
|
||||
|
||||
INLINE BuilderVertexTempl &set_pixel_size(float s);
|
||||
|
||||
bool operator == (const BuilderVertexTempl &other) const;
|
||||
bool operator < (const BuilderVertexTempl &other) const;
|
||||
|
||||
ostream &output(ostream &out) const;
|
||||
|
||||
protected:
|
||||
VType _coord;
|
||||
TType _texcoord;
|
||||
};
|
||||
|
||||
template <class VT, class NT, class TT, class CT>
|
||||
INLINE ostream &operator << (ostream &out,
|
||||
const BuilderVertexTempl<VT, NT, TT, CT> &vertex) {
|
||||
return vertex.output(out);
|
||||
}
|
||||
|
||||
|
||||
#include "builderVertexTempl.I"
|
||||
|
||||
#endif
|
||||
14
panda/src/builder/config_builder.cxx
Normal file
14
panda/src/builder/config_builder.cxx
Normal file
@@ -0,0 +1,14 @@
|
||||
// Filename: config_builder.cxx
|
||||
// Created by: drose (29Feb00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_builder.h"
|
||||
|
||||
#include <dconfig.h>
|
||||
|
||||
Configure(config_builder);
|
||||
NotifyCategoryDef(builder, "");
|
||||
|
||||
ConfigureFn(config_builder) {
|
||||
}
|
||||
14
panda/src/builder/config_builder.h
Normal file
14
panda/src/builder/config_builder.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Filename: config_builder.h
|
||||
// Created by: drose (29Feb00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_BUILDER_H
|
||||
#define CONFIG_BUILDER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include <notifyCategoryProxy.h>
|
||||
|
||||
NotifyCategoryDecl(builder, EXPCL_PANDAEGG, EXPTP_PANDAEGG);
|
||||
|
||||
#endif
|
||||
11
panda/src/builder/mesher.cxx
Normal file
11
panda/src/builder/mesher.cxx
Normal file
@@ -0,0 +1,11 @@
|
||||
// Filename: mesher.cxx
|
||||
// Created by: drose (11May00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "mesher.h"
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma implementation
|
||||
#endif
|
||||
42
panda/src/builder/mesher.h
Normal file
42
panda/src/builder/mesher.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// Filename: mesher.h
|
||||
// Created by: drose (17Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
#ifndef MESHER_H
|
||||
#define MESHER_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "mesherFanMaker.h"
|
||||
#include "mesherEdge.h"
|
||||
#include "mesherStrip.h"
|
||||
#include "mesherTempl.h"
|
||||
#include "builderPrim.h"
|
||||
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherFanMaker<BuilderPrim>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherEdge<BuilderPrim>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherStrip<BuilderPrim>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherTempl<BuilderPrim>);
|
||||
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherFanMaker<BuilderPrimI>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherEdge<BuilderPrimI>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherStrip<BuilderPrimI>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, MesherTempl<BuilderPrimI>);
|
||||
|
||||
class EXPCL_PANDAEGG Mesher : public MesherTempl<BuilderPrim> {
|
||||
public:
|
||||
Mesher(BuilderBucket *bucket) : MesherTempl<BuilderPrim>(bucket) {}
|
||||
};
|
||||
|
||||
class EXPCL_PANDAEGG MesherI : public MesherTempl<BuilderPrimI> {
|
||||
public:
|
||||
MesherI(BuilderBucket *bucket) : MesherTempl<BuilderPrimI>(bucket) {}
|
||||
};
|
||||
|
||||
// Tell GCC that we'll take care of the instantiation explicitly here.
|
||||
#ifdef __GNUC__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
143
panda/src/builder/mesherEdge.I
Normal file
143
panda/src/builder/mesherEdge.I
Normal file
@@ -0,0 +1,143 @@
|
||||
// Filename: mesherEdge.I
|
||||
// Created by: drose (15Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
template <class PrimType>
|
||||
INLINE MesherEdge<PrimType>::
|
||||
MesherEdge(const Vertex *a, const Vertex *b) : _a(a), _b(b) {
|
||||
_opposite = NULL;
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE MesherEdge<PrimType>::
|
||||
MesherEdge(const MesherEdge ©) :
|
||||
_a(copy._a),
|
||||
_b(copy._b),
|
||||
_strips(copy._strips),
|
||||
_opposite(copy._opposite)
|
||||
{
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherEdge<PrimType>::
|
||||
contains_vertex(const Vertex *v) const {
|
||||
return (_a==v || _b==v);
|
||||
}
|
||||
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherEdge<PrimType>::
|
||||
matches(const MesherEdge &other) const {
|
||||
return (_a == other._a && _b == other._b) ||
|
||||
(_b == other._a && _a == other._b);
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE MesherEdge<PrimType> *MesherEdge<PrimType>::
|
||||
common_ptr() {
|
||||
return min(this, _opposite);
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherEdge<PrimType>::
|
||||
operator == (const MesherEdge &other) const {
|
||||
return _a == other._a && _b == other._b;
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherEdge<PrimType>::
|
||||
operator < (const MesherEdge &other) const {
|
||||
return _a < other._a || (_a == other._a && _b < other._b);
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE float MesherEdge<PrimType>::
|
||||
compute_length(const BuilderBucket &bucket) const {
|
||||
LVector3f v = ((const Vertexf &)_a->get_coord_value(bucket) -
|
||||
(const Vertexf &)_b->get_coord_value(bucket));
|
||||
return length(v);
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE Vertexf MesherEdge<PrimType>::
|
||||
compute_box(const BuilderBucket &bucket) const {
|
||||
LVector3f v = ((const Vertexf &)_a->get_coord_value(bucket) -
|
||||
(const Vertexf &)_b->get_coord_value(bucket));
|
||||
return Vertexf(fabs(v[0]), fabs(v[1]), fabs(v[2]));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MesherEdge::remove
|
||||
// Access: Public
|
||||
// Description: Removes an edge from a particular strip.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType>
|
||||
void MesherEdge<PrimType>::
|
||||
remove(Strip *strip) {
|
||||
strip->_edges.remove(this);
|
||||
strip->_edges.remove(_opposite);
|
||||
|
||||
_strips.remove(strip);
|
||||
_opposite->_strips.remove(strip);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MesherEdge::change_strip
|
||||
// Access: Public
|
||||
// Description: Reparents the edge from strip "from" to strip "to".
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType>
|
||||
void MesherEdge<PrimType>::
|
||||
change_strip(Strip *from, Strip *to) {
|
||||
Strips::iterator si;
|
||||
|
||||
for (si = _strips.begin(); si != _strips.end(); ++si) {
|
||||
if (*si == from) {
|
||||
*si = to;
|
||||
}
|
||||
}
|
||||
|
||||
for (si = _opposite->_strips.begin();
|
||||
si != _opposite->_strips.end();
|
||||
++si) {
|
||||
if (*si == from) {
|
||||
*si = to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MesherEdge::output
|
||||
// Access: Public
|
||||
// Description: Formats the edge for output in some sensible way.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType>
|
||||
ostream &MesherEdge<PrimType>::
|
||||
output(ostream &out) const {
|
||||
out << "Edge [" << *_a << " to " << *_b << "], "
|
||||
<< _strips.size() << " strips:";
|
||||
|
||||
Strips::const_iterator si;
|
||||
for (si = _strips.begin(); si != _strips.end(); ++si) {
|
||||
out << " " << (*si)->_index;
|
||||
}
|
||||
|
||||
if (_opposite!=NULL) {
|
||||
out << " opposite "
|
||||
<< _opposite->_strips.size() << " strips:";
|
||||
|
||||
for (si = _opposite->_strips.begin();
|
||||
si != _opposite->_strips.end();
|
||||
++si) {
|
||||
out << " " << (*si)->_index;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
62
panda/src/builder/mesherEdge.h
Normal file
62
panda/src/builder/mesherEdge.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// Filename: mesherEdge.h
|
||||
// Created by: drose (15Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MESHEREDGE_H
|
||||
#define MESHEREDGE_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#include "builderBucket.h"
|
||||
|
||||
#include <list>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
template <class PrimType>
|
||||
class MesherStrip;
|
||||
|
||||
template <class PrimType>
|
||||
class MesherEdge {
|
||||
public:
|
||||
typedef PrimType Prim;
|
||||
typedef TYPENAME PrimType::Vertex Vertex;
|
||||
typedef MesherStrip<PrimType> Strip;
|
||||
|
||||
INLINE MesherEdge(const Vertex *a, const Vertex *b);
|
||||
INLINE MesherEdge(const MesherEdge ©);
|
||||
|
||||
void remove(Strip *strip);
|
||||
void change_strip(Strip *from, Strip *to);
|
||||
|
||||
INLINE bool contains_vertex(const Vertex *v) const;
|
||||
|
||||
INLINE bool matches(const MesherEdge &other) const;
|
||||
|
||||
INLINE MesherEdge *common_ptr();
|
||||
|
||||
INLINE bool operator == (const MesherEdge &other) const;
|
||||
INLINE bool operator < (const MesherEdge &other) const;
|
||||
|
||||
INLINE float compute_length(const BuilderBucket &bucket) const;
|
||||
INLINE Vertexf compute_box(const BuilderBucket &bucket) const;
|
||||
|
||||
ostream &output(ostream &out) const;
|
||||
|
||||
const Vertex *_a, *_b;
|
||||
|
||||
typedef list<Strip *> Strips;
|
||||
Strips _strips;
|
||||
MesherEdge *_opposite;
|
||||
};
|
||||
|
||||
template <class PrimType>
|
||||
INLINE ostream &operator << (ostream &out,
|
||||
const MesherEdge<PrimType> &edge) {
|
||||
return edge.output(out);
|
||||
}
|
||||
|
||||
#include "mesherEdge.I"
|
||||
|
||||
#endif
|
||||
312
panda/src/builder/mesherFanMaker.I
Normal file
312
panda/src/builder/mesherFanMaker.I
Normal file
@@ -0,0 +1,312 @@
|
||||
// Filename: mesherFanMaker.I
|
||||
// Created by: drose (21Sep97)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "builderFuncs.h"
|
||||
|
||||
#include <notify.h>
|
||||
#include <mathNumbers.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherFanMaker<PrimType>::
|
||||
operator < (const MesherFanMaker &other) const {
|
||||
return _edges.front() < other._edges.front();
|
||||
}
|
||||
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherFanMaker<PrimType>::
|
||||
operator == (const MesherFanMaker &other) const {
|
||||
return _edges.front() == other._edges.front();
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherFanMaker<PrimType>::
|
||||
is_empty() const {
|
||||
return (_edges.empty());
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
INLINE bool MesherFanMaker<PrimType>::
|
||||
is_valid() const {
|
||||
return (_edges.size() > 2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MesherFanMaker::is_coplanar_with
|
||||
// Access: Public
|
||||
// Description: Returns true if the strip and the other strip are
|
||||
// coplanar.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template <class PrimType>
|
||||
INLINE bool MesherFanMaker<PrimType>::
|
||||
is_coplanar_with(const MesherFanMaker &other) const {
|
||||
return _planar && other._planar &&
|
||||
_strips.front()->is_coplanar_with(*other._strips.front(),
|
||||
_bucket->_coplanar_threshold);
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
MesherFanMaker<PrimType>::
|
||||
MesherFanMaker(const Vertex *vertex, Strip *tri, Mesher *mesher) {
|
||||
_vertex = vertex;
|
||||
_edges.push_back(tri->find_opposite_edge(vertex));
|
||||
_strips.push_back(tri);
|
||||
_planar = tri->_planar;
|
||||
_mesher = mesher;
|
||||
_bucket = _mesher->_bucket;
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
bool MesherFanMaker<PrimType>::
|
||||
join(MesherFanMaker &other) {
|
||||
nassertr(_vertex == other._vertex, false);
|
||||
nassertr(_mesher == other._mesher, false);
|
||||
nassertr(_bucket == other._bucket, false);
|
||||
|
||||
if (_edges.back()->_b == other._edges.front()->_a) {
|
||||
_planar = is_coplanar_with(other);
|
||||
_edges.splice(_edges.end(), other._edges);
|
||||
_strips.splice(_strips.end(), other._strips);
|
||||
return true;
|
||||
} else if (_edges.front()->_a == other._edges.back()->_b) {
|
||||
_planar = is_coplanar_with(other);
|
||||
_edges.splice(_edges.begin(), other._edges);
|
||||
_strips.splice(_strips.begin(), other._strips);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class PrimType>
|
||||
float MesherFanMaker<PrimType>::
|
||||
compute_angle() const {
|
||||
// We sum up the angles of each triangle. This is more correct than
|
||||
// taking the net angle from the first edge to the last (since we
|
||||
// may not be in a plane).
|
||||
nassertr(is_valid(), 0.0);
|
||||
|
||||
double angle = 0.0;
|
||||
Vertexf v0 = _vertex->get_coord_value(*_bucket);
|
||||
|
||||
Edges::const_iterator ei;
|
||||
for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
|
||||
Normalf v1 = (Vertexf &)(*ei)->_a->get_coord_value(*_bucket) - v0;
|
||||
Normalf v2 = (Vertexf &)(*ei)->_b->get_coord_value(*_bucket) - v0;
|
||||
|
||||
v1 = normalize(v1);
|
||||
v2 = normalize(v2);
|
||||
angle += acos(dot(v1, v2));
|
||||
}
|
||||
|
||||
return angle * 180.0 / MathNumbers::pi;
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
int MesherFanMaker<PrimType>::
|
||||
build() {
|
||||
nassertr(_edges.size() == _strips.size(), 0);
|
||||
|
||||
int num_tris = _edges.size();
|
||||
float net_angle = compute_angle();
|
||||
float avg_angle = net_angle / num_tris;
|
||||
|
||||
if (avg_angle > _bucket->_max_tfan_angle) {
|
||||
// The triangles are too loose to justify making a fan; it'll
|
||||
// probably make a better quadsheet.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_bucket->_min_tfan_tris==0 || num_tris < _bucket->_min_tfan_tris) {
|
||||
// Oops, not enough triangles to justify a fan.
|
||||
if (!_bucket->_unroll_fans) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// However, we could (maybe) make it a few tristrips!
|
||||
|
||||
// Each section of the fan which is made up of coplanar tris with
|
||||
// identical properties may be retesselated into a tristrip. What
|
||||
// a sneaky trick! To do this, we must first identify each such
|
||||
// qualifying section.
|
||||
|
||||
// We define a seam as the edge between any two tris which are
|
||||
// noncoplanar or which do not share identical properties. Then
|
||||
// we can send each piece between the seams to unroll().
|
||||
|
||||
Strips::iterator si, last_si;
|
||||
Edges::iterator ei, last_ei;
|
||||
|
||||
// First, rotate the fan so it begins at a seam. We do this so we
|
||||
// won't be left out with part of one piece at the beginning and
|
||||
// also at the end.
|
||||
si = _strips.begin();
|
||||
last_si = si;
|
||||
ei = _edges.begin();
|
||||
last_ei = ei;
|
||||
int found_seam = false;
|
||||
|
||||
for (++si, ++ei; si != _strips.end() && !found_seam; ++si, ++ei) {
|
||||
nassertr(ei != _edges.end(), 0);
|
||||
if ( !((*si)->_prims.front() == (*last_si)->_prims.front()) ||
|
||||
!(*si)->is_coplanar_with(*(*last_si), _bucket->_coplanar_threshold)) {
|
||||
// Here's a seam. Break the fan here.
|
||||
found_seam = true;
|
||||
_edges.splice(_edges.begin(), _edges, ei, _edges.end());
|
||||
_strips.splice(_strips.begin(), _strips, si, _strips.end());
|
||||
}
|
||||
}
|
||||
|
||||
// Now break the fan up along its seams and unroll each piece
|
||||
// separately.
|
||||
si = _strips.begin();
|
||||
last_si = si;
|
||||
ei = _edges.begin();
|
||||
last_ei = ei;
|
||||
|
||||
int count = 0;
|
||||
for (++si, ++ei; si != _strips.end(); ++si, ++ei) {
|
||||
nassertr(ei != _edges.end(), 0);
|
||||
if ( !((*si)->_prims.front() == (*last_si)->_prims.front()) ||
|
||||
!(*si)->is_coplanar_with(*(*last_si), _bucket->_coplanar_threshold)) {
|
||||
// Here's the end of a run of matching pieces.
|
||||
count += unroll(last_si, si, last_ei, ei);
|
||||
last_si = si;
|
||||
last_ei = ei;
|
||||
}
|
||||
}
|
||||
count += unroll(last_si, si, last_ei, ei);
|
||||
|
||||
return count;
|
||||
|
||||
} else {
|
||||
Strip new_fan;
|
||||
new_fan._type = BPT_trifan;
|
||||
new_fan._verts.push_back(_vertex);
|
||||
|
||||
new_fan._verts.push_back(_edges.front()->_a);
|
||||
Edges::iterator ei;
|
||||
for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
|
||||
new_fan._verts.push_back((*ei)->_b);
|
||||
}
|
||||
|
||||
Strips::iterator si;
|
||||
for (si = _strips.begin(); si != _strips.end(); ++si) {
|
||||
new_fan._prims.splice(new_fan._prims.end(), (*si)->_prims);
|
||||
(*si)->remove_all_edges();
|
||||
(*si)->_verts.clear();
|
||||
(*si)->_status = MS_dead;
|
||||
}
|
||||
|
||||
// If we'd built our list of edges and strips right, this sum should
|
||||
// come out so that there are two more vertices than triangles in
|
||||
// the new fan.
|
||||
nassertr(new_fan._verts.size() == new_fan._prims.size() + 2, 0);
|
||||
|
||||
// Now we've built a fan, and it won't be able to mate with
|
||||
// anything else, so add it to the done list.
|
||||
_mesher->_done.push_back(new_fan);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class PrimType>
|
||||
int MesherFanMaker<PrimType>::
|
||||
unroll(Strips::iterator strip_begin, Strips::iterator strip_end,
|
||||
Edges::iterator edge_begin, Edges::iterator edge_end) {
|
||||
Edges::iterator ei;
|
||||
Strips::iterator si;
|
||||
|
||||
int num_tris = 0;
|
||||
for (ei = edge_begin; ei != edge_end; ++ei) {
|
||||
num_tris++;
|
||||
}
|
||||
|
||||
if (num_tris < 3) {
|
||||
// Don't even bother.
|
||||
return 0;
|
||||
}
|
||||
|
||||
Prim poly;
|
||||
|
||||
// Now we build an n-sided polygon. We'll decompose it into tris
|
||||
// in a second.
|
||||
poly.set_type(BPT_poly);
|
||||
poly.set_attrib((*strip_begin)->_prims.front());
|
||||
|
||||
ei = edge_end;
|
||||
--ei;
|
||||
if ( !((*ei)->_b == (*edge_begin)->_a)) {
|
||||
// If the fan is less than a full circle, we need to keep the
|
||||
// hub vertex and initial vertex in the poly. Otherwise, we'll
|
||||
// discard them.
|
||||
poly.add_vertex(*_vertex);
|
||||
poly.add_vertex(*(*edge_begin)->_a);
|
||||
}
|
||||
|
||||
for (ei = edge_begin; ei != edge_end; ++ei) {
|
||||
poly.add_vertex(*(*ei)->_b);
|
||||
}
|
||||
|
||||
int result = true;
|
||||
|
||||
if (_bucket->_show_quads) {
|
||||
// If we're showing quads, also show retesselated triangles.
|
||||
_mesher->add_prim(poly, MO_fanpoly);
|
||||
|
||||
} else {
|
||||
// Now decompose the new polygon into triangles.
|
||||
vector<Prim> tris;
|
||||
result = expand(poly, *_bucket, back_inserter(tris));
|
||||
|
||||
if (result) {
|
||||
// Now add each triangle back into the mesher.
|
||||
vector<Prim>::iterator ti;
|
||||
|
||||
for (ti = tris.begin(); ti != tris.end(); ++ti) {
|
||||
_mesher->add_prim(*ti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
// Now that we've created a new poly, kill off all the old ones.
|
||||
for (si = strip_begin; si != strip_end; ++si) {
|
||||
(*si)->remove_all_edges();
|
||||
(*si)->_verts.clear();
|
||||
(*si)->_prims.clear();
|
||||
(*si)->_status = MS_dead;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class PrimType>
|
||||
ostream &MesherFanMaker<PrimType>::
|
||||
output(ostream &out) const {
|
||||
out << *_vertex << ":[";
|
||||
if (!_edges.empty()) {
|
||||
Edges::const_iterator ei;
|
||||
for (ei = _edges.begin(); ei != _edges.end(); ++ei) {
|
||||
out << " " << *(*ei)->_a;
|
||||
}
|
||||
out << " " << *_edges.back()->_b;
|
||||
}
|
||||
out << " ]";
|
||||
|
||||
if (_planar) {
|
||||
out << " (planar)";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user