Add libprojectm to 3rdparty

This commit is contained in:
David Sansome 2010-06-06 21:43:45 +00:00
parent 0e155c1eaf
commit 313daa5fd4
162 changed files with 66792 additions and 0 deletions

170
3rdparty/libprojectm/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,170 @@
PROJECT(projectM)
cmake_minimum_required(VERSION 2.6.0)
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The projectM core library.")
cmake_policy(SET CMP0005 OLD)
OPTION (USE_DEVIL "Use devIL for image loading rather than the builtin SOIL library" OFF)
OPTION (USE_FBO "Use Framebuffer Objects for increased rendering quality. Disable this for OpenGL ES 1.x or if you are experiencing problems on older or poorly supported hardware." ON)
OPTION(USE_FTGL "Use FTGL for on-screen fonts (found on your system)" OFF)
OPTION (USE_GLES1 "Use OpenGL ES 1.x" OFF)
OPTION (USE_THREADS "Use threads for parallelization" OFF)
OPTION (USE_OPENMP "Use OpenMP and OMPTL for multi-core parallelization" ON)
OPTION (USE_NATIVE_GLEW "Use projectM's native implemention of GLEW." OFF)
OPTION (USE_CG "Use Cg for Pixel Shader support" OFF)
OPTION (BUILD_PROJECTM_STATIC "Build the projectM target library in the platform's native static (NOT shared) format." ON)
OPTION (DISABLE_NATIVE_PRESETS "Turn off support for native (C++ style) presets" OFF)
OPTION (DISABLE_MILKDROP_PRESETS "Turn off support for Milkdrop (.milk / .prjm) presets" OFF)
ADD_DEFINITIONS(-DCMAKE_INSTALL_PREFIX="\\\"${CMAKE_INSTALL_PREFIX}\\\"")
if (USE_NATIVE_GLEW)
ADD_DEFINITIONS(-DUSE_NATIVE_GLEW)
SET(GLEW_SOURCES glew.h glew.c)
SET(GLEW_LINK_TARGETS )
else(USE_NATIVE_GLEW)
SET(GLEW_SOURCES )
SET (GLEW_LINK_TARGETS GLEW)
endif(USE_NATIVE_GLEW)
SET(projectM_SOURCES projectM.cpp PCM.cpp Preset.cpp fftsg.cpp KeyHandler.cpp
timer.cpp wipemalloc.cpp PresetLoader.cpp PresetChooser.cpp PipelineMerger.cpp ConfigFile.cpp TimeKeeper.cpp PresetFactory.cpp PresetFactoryManager.cpp ${GLEW_SOURCES})
if (MSVC)
SET(projectM_SOURCES ${projectM_SOURCES} dlfcn.c win32-dirent.cpp)
endif(MSVC)
if (NOT DISABLE_NATIVE_PRESETS)
add_subdirectory(NativePresetFactory)
SET(PRESET_FACTORY_SOURCES ${PRESET_FACTORY_SOURCES} ${NativePresetFactory_SOURCE_DIR})
SET(PRESET_FACTORY_BINARY_DIR ${PRESET_FACTORY_BINARY_DIR} ${NativePresetFactory_BINARY_DIR})
SET(PRESET_FACTORY_LINK_TARGETS ${PRESET_FACTORY_LINK_TARGETS} NativePresetFactory)
endif(NOT DISABLE_NATIVE_PRESETS)
if (NOT DISABLE_MILKDROP_PRESETS)
add_subdirectory(MilkdropPresetFactory)
SET(PRESET_FACTORY_SOURCES ${PRESET_FACTORY_SOURCES} ${MilkdropPresetFactory_SOURCE_DIR})
SET(PRESET_FACTORY_BINARY_DIR ${PRESET_FACTORY_BINARY_DIR} ${MilkdropPrmaesetFactory_BINARY_DIR})
SET(PRESET_FACTORY_LINK_TARGETS ${PRESET_FACTORY_LINK_TARGETS} MilkdropPresetFactory)
endif(NOT DISABLE_MILKDROP_PRESETS)
if (USE_DEVIL)
SET (projectM_SOURCES ${projectM_SOURCES})
ADD_DEFINITIONS(-DUSE_DEVIL)
SET (IMAGE_LINK_TARGETS IL ILU ILUT)
else (USE_DEVIL)
SET (projectM_SOURCES ${projectM_SOURCES})
SET (IMAGE_LINK_TARGETS )
endif (USE_DEVIL)
if (USE_CG)
ADD_DEFINITIONS(-DUSE_CG)
SET (CG_LINK_TARGETS Cg CgGL)
else (USE_CG)
SET (CG_LINK_TARGETS)
endif(USE_CG)
if(USE_GLES1)
ADD_DEFINITIONS(-DUSE_GLES1)
endif(USE_GLES1)
if(USE_FBO)
ADD_DEFINITIONS(-DUSE_FBO)
endif(USE_FBO)
if(USE_FTGL)
ADD_DEFINITIONS(-DUSE_FTGL)
find_package( Freetype2 REQUIRED)
include_directories( ${FREETYPE2_INCLUDE_DIR} )
endif(USE_FTGL)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
if (BUILD_PROJECTM_STATIC)
ADD_LIBRARY(projectM STATIC ${projectM_SOURCES})
else(BUILD_PROJECTM_STATIC)
ADD_LIBRARY(projectM SHARED ${projectM_SOURCES})
endif(BUILD_PROJECTM_STATIC)
SET_TARGET_PROPERTIES(projectM PROPERTIES VERSION 2.00 SOVERSION 2)
if (USE_THREADS)
ADD_DEFINITIONS(-DUSE_THREADS)
endif(USE_THREADS)
if (APPLE)
ADD_DEFINITIONS(-DMACOS -DSTBI_NO_DDS)
set(RESOURCE_PREFIX "Resources")
else (APPLE)
if (WIN32)
set (RESOURCE_PREFIX "Resources")
ADD_DEFINITIONS(-DWIN32 -DSTBI_NO_DDS)
else(WIN32)
set (RESOURCE_PREFIX "share/projectM")
ADD_DEFINITIONS(-DLINUX -DSTBI_NO_DDS)
endif(WIN32)
endif(APPLE)
add_subdirectory(Renderer)
#ADD_DEFINITIONS(-DCMAKE_INSTALL_PREFIX="\\\"${CMAKE_INSTALL_PREFIX}\\\"")
FIND_PACKAGE(OpenGL)
#set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH};/opt/local/include;/Developer/SDKs/MACOSX10.5.sdk/usr/X11/include)
#set(CMAKE_LIBRARY_PATH /opt/local/lib;/Developer/SDKs/MACOSX10.5.sdk;/Developer/SDKs/MacOSX10.5.sdk/usr/X11/lib/)
IF(USE_OPENMP)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ")
ENDIF(USE_OPENMP)
INCLUDE_DIRECTORIES(${projectM_SOURCE_DIR} ${FTGL_INCLUDE_DIRS} ${Renderer_SOURCE_DIR} ${PRESET_FACTORY_SOURCES})
LINK_DIRECTORIES(${FTGL_LINK_DIRS} ${Renderer_BINARY_DIR} ${PRESET_FACTORY_BINARY_DIR})
if(MSVC)
SET (MATH_LIBRARIES )
else(MSVC)
SET (MATH_LIBRARIES m)
endif(MSVC)
if(BUILD_PROJECTM_STATIC)
TARGET_LINK_LIBRARIES(projectM ${GLEW_LINK_TARGETS} ${MATH_LIBRARIES} ${FTGL_LINK_TARGETS} ${OPENGL_LIBRARIES} ${IMAGE_LINK_TARGETS} ${CG_LINK_TARGETS} ${PRESET_FACTORY_LINK_TARGETS})
else(BUILD_PROJECTM_STATIC)
TARGET_LINK_LIBRARIES(projectM ${GLEW_LINK_TARGETS} ${MATH_LIBRARIES} ${FTGL_LINK_TARGETS} ${OPENGL_LIBRARIES} ${IMAGE_LINK_TARGETS} ${CG_LINK_TARGETS} ${PRESET_FACTORY_LINK_TARGETS})
endif(BUILD_PROJECTM_STATIC)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/libprojectM.pc.in" "${CMAKE_CURRENT_SOURCE_DIR}/libprojectM.pc" @ONLY)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/config.inp.in" "${CMAKE_CURRENT_SOURCE_DIR}/config.inp" @ONLY)
FILE(GLOB presets "presets/*.milk" "presets/*.prjm" "presets/*.tga")
INSTALL(FILES ${presets} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/projectM/presets)
FILE(GLOB fonts "fonts/*.ttf")
INSTALL(FILES ${fonts} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/projectM/fonts)
INSTALL(FILES ${Renderer_SOURCE_DIR}/projectM.cg ${Renderer_SOURCE_DIR}/blur.cg DESTINATION ${CMAKE_INSTALL_PREFIX}/share/projectM/shaders)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libprojectM.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.inp DESTINATION ${CMAKE_INSTALL_PREFIX}/share/projectM)
INSTALL(FILES projectM.hpp event.h dlldefs.h fatal.h PCM.hpp Common.hpp DESTINATION include/libprojectM)
INSTALL(TARGETS projectM DESTINATION lib${LIB_SUFFIX})

21
3rdparty/libprojectm/COPYING vendored Normal file
View File

@ -0,0 +1,21 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2009 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/

96
3rdparty/libprojectm/ChangeLog vendored Normal file
View File

@ -0,0 +1,96 @@
New for version 1.1
------------------------------------------------------
* general performance improvements and improved video card compatability
* multi-threading during smooth preset switching
* pulse audio support
* Qt4 GUI implemented for playlist management and preset editing (jack / pulseaudio only)
New for versoin 1.01
------------------------------------------------------
* Bugfixes
New for version 1.00
------------------------------------------------------
This release includes months of refactoring. The code changes are immense. The list below does not even begin to explain the amount of upheaval that has occured.
*Smooth Preset Switching
*OpenGL Framebuffer Objects (sharper rendering)
*PerPixel Warp effect added
*Custom Shape Texturing via Images (imageURL property)
*Serious Parser/Evaluator improvements for better .milk Compatability
*projectM-engine can render to a texture instead of the framebuffer (see projectM-test/projectM-test-texture.cpp)
*projectM-engine, projectM-xmms, projectM-jack, and projectM-test build system converted to CMake
*3D Song title animation
*New Configuration File (more options, more flexible)
New for version 0.99
------------------------------------------------------
*config file now saved at ~/.projectM/config
*internal rendering coordinate spaces corrected. (basically, I made some stupid decisions a long time ago, and just fixed them now)
*xmms plugins close properly via window decorations
*mouse cursor hidden in xmms-projectM during fullscreen
*menus should resize relative to the screen size now
*Fixed numerous compilation bugs
*when the player changes to a new song, libprojectM will zoom in the title for a few seconds, then blend the title into the vis (ala milkdrop), if the player support sending the title to libprojectM (only xmms-projectM now)
New for version 0.98
------------------------------------------------------
*projectM has been refactored into a shared library called libprojectM.
-Now compiles as C++ (even though 99% of the code is C)
*libvisual-projectM now supports libvisual 0.4.0
*Preset library updated (~150 new, ~25 removed)
*Improved Rendering Engine
-rewrote per pixel mathematics
-fixed waveforms 0, 1, and 4
-fixed Order of drawing (Vectors, Custom Shapes, Custom Waves, Waveform, Borders)
-fixed custom shape rotation and texture parameter bugs
-added support for the bDarkenCenter feature
-added pbuffer support (however, you can't use it yet)
-improved motion vectors when using pbuffers
*Improved .milk Parser
-corrected behavior of frame, wave, and shape init_eqns
-fixed bug with multiple equations on one line
*Menu/Help/Display System Improvements
-Replaced GLF with FTGL (TrueType) fonts.
-Added the solarize, brighten, darken, and invert filters to the post-processing menu
-(F4) new Rendering stats display
-(F5) Framerate display fixed
*New Framerate limiter
*n0dalus contributed some autotools patches.
*Chris Byrne of Monstavision contributed:
-3 Memory Leak fixes!
-Performance improvements during PCM input
-Preset index code rewritten to allow presets to be added while projectM is running
*Hai Zaar helped us clean up the autotools stuff
-Presets/fonts will be stored in $DATADIR/projectM/fonts and /presets
-The config file will be stored in $SYSCONFDIR/projectM
-By default DATADIR is $PREFIX/share and SYSCONFDIR is $PREFIX/etc
so we reccomend you run configure like so:
./configure --sysconfdir=/etc

245
3rdparty/libprojectm/Common.hpp vendored Executable file
View File

@ -0,0 +1,245 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* $Log$
*/
#ifndef COMMON_HPP
#define COMMON_HPP
#include <vector>
#include <typeinfo>
#include <cstdarg>
#include <cassert>
#ifdef _MSC_sVER
#define strcasecmp(s, t) _strcmpi(s, t)
#endif
#ifdef _MSC_VER
#pragma warning( disable : 4244 4305 4996; once : 4018 )
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
typedef unsigned int uint;
#endif
#ifdef DEBUG
//extern FILE *debugFile;
#endif
#ifdef MACOS
#include <cstdio>
extern FILE *fmemopen(void *buf, size_t len, const char *pMode);
#endif /** MACOS */
#include "dlldefs.h"
#define DEFAULT_FONT_PATH "/home/carm/fonts/courier1.glf"
#define MAX_TOKEN_SIZE 512
#define MAX_PATH_SIZE 4096
#define STRING_BUFFER_SIZE 1024*150
#define STRING_LINE_SIZE 1024
#ifdef LINUX
#include <cstdlib>
#define projectM_isnan isnan
#endif
#ifdef WIN32
#define projectM_isnan(x) ((x) != (x))
#endif
#ifdef MACOS
#define projectM_isnan(x) ((x) != (x))
#endif
#ifdef LINUX
#define projectM_fmax fmax
#endif
#ifdef WIN32
#define projectM_fmax(x,y) ((x) >= (y) ? (x): (y))
#endif
#ifdef MACOS
#define projectM_fmax(x,y) ((x) >= (y) ? (x): (y))
#endif
#ifdef LINUX
#define projectM_fmin fmin
#endif
#ifdef WIN32
#define projectM_fmin(x,y) ((x) <= (y) ? (x): (y))
#endif
#ifdef MACOS
#define projectM_fmin(x,y) ((x) <= (y) ? (x): (y))
#endif
#ifndef TRUE
#define TRUE true
#endif
#ifndef FALSE
#define FALSE false
#endif
#define MAX_DOUBLE_SIZE 10000000.0
#define MIN_DOUBLE_SIZE -10000000.0
#define MAX_INT_SIZE 10000000
#define MIN_INT_SIZE -10000000
/* default float initial value */
#define DEFAULT_DOUBLE_IV 0.0
/* default float lower bound */
#define DEFAULT_DOUBLE_LB MIN_DOUBLE_SIZE
/* default float upper bound */
#define DEFAULT_DOUBLE_UB MAX_DOUBLE_SIZE
#ifdef WIN32
#include <float.h>
#define isnan _isnan
#endif /** WIN32 */
/** Per-platform path separators */
#define WIN32_PATH_SEPARATOR '\\'
#define UNIX_PATH_SEPARATOR '/'
#ifdef WIN32
#define PATH_SEPARATOR WIN32_PATH_SEPARATOR
#else
#define PATH_SEPARATOR UNIX_PATH_SEPARATOR
#endif /** WIN32 */
#include <string>
const unsigned int NUM_Q_VARIABLES(32);
const std::string PROJECTM_FILE_EXTENSION("prjm");
const std::string MILKDROP_FILE_EXTENSION("milk");
const std::string PROJECTM_MODULE_EXTENSION("so");
template <class TraverseFunctor, class Container>
void traverse(Container & container)
{
TraverseFunctor functor;
for (typename Container::iterator pos = container.begin(); pos != container.end(); ++pos)
{
assert(pos->second);
functor(pos->second);
}
}
template <class TraverseFunctor, class Container>
void traverseVector(Container & container)
{
TraverseFunctor functor;
for (typename Container::iterator pos = container.begin(); pos != container.end(); ++pos)
{
assert(*pos);
functor(*pos);
}
}
template <class TraverseFunctor, class Container>
void traverse(Container & container, TraverseFunctor & functor)
{
for (typename Container::iterator pos = container.begin(); pos != container.end(); ++pos)
{
assert(pos->second);
functor(pos->second);
}
}
namespace TraverseFunctors
{
template <class Data>
class Delete
{
public:
void operator() (Data * data)
{
assert(data);
delete(data);
}
};
}
inline std::string parseExtension(const std::string & filename) {
const std::size_t start = filename.find_last_of('.');
if (start == std::string::npos || start >= (filename.length()-1))
return "";
else
return filename.substr(start+1, filename.length());
}
inline std::string parseFilename(const std::string & filename) {
const std::size_t start = filename.find_last_of('/');
if (start == std::string::npos || start >= (filename.length()-1))
return "";
else
return filename.substr(start+1, filename.length());
}
inline double meanSquaredError(const double & x, const double & y) {
return (x-y)*(x-y);
}
enum PresetRatingType {
FIRST_RATING_TYPE = 0,
HARD_CUT_RATING_TYPE = FIRST_RATING_TYPE,
SOFT_CUT_RATING_TYPE,
LAST_RATING_TYPE = SOFT_CUT_RATING_TYPE,
TOTAL_RATING_TYPES = SOFT_CUT_RATING_TYPE+1
};
typedef std::vector<int> RatingList;
#endif

142
3rdparty/libprojectm/ConfigFile.cpp vendored Normal file
View File

@ -0,0 +1,142 @@
// ConfigFile.cpp
#include "ConfigFile.h"
using std::string;
ConfigFile::ConfigFile( string filename, string delimiter,
string comment, string sentry )
: myDelimiter(delimiter), myComment(comment), mySentry(sentry)
{
// Construct a ConfigFile, getting keys and values from given file
std::ifstream in( filename.c_str() );
if( !in ) throw file_not_found( filename );
in >> (*this);
}
ConfigFile::ConfigFile()
: myDelimiter( string(1,'=') ), myComment( string(1,'#') )
{
// Construct a ConfigFile without a file; empty
}
void ConfigFile::remove( const string& key )
{
// Remove key and its value
myContents.erase( myContents.find( key ) );
return;
}
bool ConfigFile::keyExists( const string& key ) const
{
// Indicate whether key is found
mapci p = myContents.find( key );
return ( p != myContents.end() );
}
/* static */
void ConfigFile::trim( string& s )
{
// Remove leading and trailing whitespace
static const char whitespace[] = " \n\t\v\r\f";
s.erase( 0, s.find_first_not_of(whitespace) );
s.erase( s.find_last_not_of(whitespace) + 1U );
}
std::ostream& operator<<( std::ostream& os, const ConfigFile& cf )
{
// Save a ConfigFile to os
for( ConfigFile::mapci p = cf.myContents.begin();
p != cf.myContents.end();
++p )
{
os << p->first << " " << cf.myDelimiter << " ";
os << p->second << std::endl;
}
return os;
}
std::istream& operator>>( std::istream& is, ConfigFile& cf )
{
// Load a ConfigFile from is
// Read in keys and values, keeping internal whitespace
typedef string::size_type pos;
const string& delim = cf.myDelimiter; // separator
const string& comm = cf.myComment; // comment
const string& sentry = cf.mySentry; // end of file sentry
const pos skip = delim.length(); // length of separator
string nextline = ""; // might need to read ahead to see where value ends
while( is || nextline.length() > 0 )
{
// Read an entire line at a time
string line;
if( nextline.length() > 0 )
{
line = nextline; // we read ahead; use it now
nextline = "";
}
else
{
std::getline( is, line );
}
// Ignore comments
line = line.substr( 0, line.find(comm) );
// Check for end of file sentry
if( sentry != "" && line.find(sentry) != string::npos ) return is;
// Parse the line if it contains a delimiter
pos delimPos = line.find( delim );
if( delimPos < string::npos )
{
// Extract the key
string key = line.substr( 0, delimPos );
line.replace( 0, delimPos+skip, "" );
// See if value continues on the next line
// Stop at blank line, next line with a key, end of stream,
// or end of file sentry
bool terminate = false;
while( !terminate && is )
{
std::getline( is, nextline );
terminate = true;
string nlcopy = nextline;
ConfigFile::trim(nlcopy);
if( nlcopy == "" ) continue;
nextline = nextline.substr( 0, nextline.find(comm) );
if( nextline.find(delim) != string::npos )
continue;
if( sentry != "" && nextline.find(sentry) != string::npos )
continue;
nlcopy = nextline;
ConfigFile::trim(nlcopy);
if( nlcopy != "" ) line += "\n";
line += nextline;
terminate = false;
}
// Store key and value
ConfigFile::trim(key);
ConfigFile::trim(line);
cf.myContents[key] = line; // overwrites if key is repeated
}
}
return is;
}

253
3rdparty/libprojectm/ConfigFile.h vendored Normal file
View File

@ -0,0 +1,253 @@
// ConfigFile.h
// Class for reading named values from configuration files
// Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu
// Copyright (c) 2004 Richard J. Wagner
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
// Typical usage
// -------------
//
// Given a configuration file "settings.inp":
// atoms = 25
// length = 8.0 # nanometers
// name = Reece Surcher
//
// Named values are read in various ways, with or without default values:
// ConfigFile config( "settings.inp" );
// int atoms = config.read<int>( "atoms" );
// double length = config.read( "length", 10.0 );
// string author, title;
// config.readInto( author, "name" );
// config.readInto( title, "title", string("Untitled") );
//
// See file example.cpp for more examples.
#ifndef CONFIGFILE_H
#define CONFIGFILE_H
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
using std::string;
class ConfigFile {
// Data
protected:
string myDelimiter; // separator between key and value
string myComment; // separator between value and comments
string mySentry; // optional string to signal end of file
std::map<string,string> myContents; // extracted keys and values
typedef std::map<string,string>::iterator mapi;
typedef std::map<string,string>::const_iterator mapci;
// Methods
public:
ConfigFile( string filename,
string delimiter = "=",
string comment = "#",
string sentry = "EndConfigFile" );
ConfigFile();
// Search for key and read value or optional default value
template<class T> T read( const string& key ) const; // call as read<T>
template<class T> T read( const string& key, const T& value ) const;
template<class T> bool readInto( T& var, const string& key ) const;
template<class T>
bool readInto( T& var, const string& key, const T& value ) const;
// Modify keys and values
template<class T> void add( string key, const T& value );
void remove( const string& key );
// Check whether key exists in configuration
bool keyExists( const string& key ) const;
// Check or change configuration syntax
string getDelimiter() const { return myDelimiter; }
string getComment() const { return myComment; }
string getSentry() const { return mySentry; }
string setDelimiter( const string& s )
{ string old = myDelimiter; myDelimiter = s; return old; }
string setComment( const string& s )
{ string old = myComment; myComment = s; return old; }
// Write or read configuration
friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf );
friend std::istream& operator>>( std::istream& is, ConfigFile& cf );
protected:
template<class T> static string T_as_string( const T& t );
template<class T> static T string_as_T( const string& s );
static void trim( string& s );
// Exception types
public:
struct file_not_found {
string filename;
file_not_found( const string& filename_ = string() )
: filename(filename_) {} };
struct key_not_found { // thrown only by T read(key) variant of read()
string key;
key_not_found( const string& key_ = string() )
: key(key_) {} };
};
/* static */
template<class T>
string ConfigFile::T_as_string( const T& t )
{
// Convert from a T to a string
// Type T must support << operator
std::ostringstream ost;
ost << t;
return ost.str();
}
/* static */
template<class T>
T ConfigFile::string_as_T( const string& s )
{
// Convert from a string to a T
// Type T must support >> operator
T t;
std::istringstream ist(s);
ist >> t;
return t;
}
/* static */
template<>
inline string ConfigFile::string_as_T<string>( const string& s )
{
// Convert from a string to a string
// In other words, do nothing
return s;
}
/* static */
template<>
inline bool ConfigFile::string_as_T<bool>( const string& s )
{
// Convert from a string to a bool
// Interpret "false", "F", "no", "n", "0" as false
// Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true
bool b = true;
string sup = s;
for( string::iterator p = sup.begin(); p != sup.end(); ++p )
*p = toupper(*p); // make string all caps
if( sup==string("FALSE") || sup==string("F") ||
sup==string("NO") || sup==string("N") ||
sup==string("0") || sup==string("NONE") )
b = false;
return b;
}
template<class T>
T ConfigFile::read( const string& key ) const
{
// Read the value corresponding to key
mapci p = myContents.find(key);
if( p == myContents.end() ) throw key_not_found(key);
return string_as_T<T>( p->second );
}
template<class T>
T ConfigFile::read( const string& key, const T& value ) const
{
// Return the value corresponding to key or given default value
// if key is not found
mapci p = myContents.find(key);
if( p == myContents.end() ) return value;
return string_as_T<T>( p->second );
}
template<class T>
bool ConfigFile::readInto( T& var, const string& key ) const
{
// Get the value corresponding to key and store in var
// Return true if key is found
// Otherwise leave var untouched
mapci p = myContents.find(key);
bool found = ( p != myContents.end() );
if( found ) var = string_as_T<T>( p->second );
return found;
}
template<class T>
bool ConfigFile::readInto( T& var, const string& key, const T& value ) const
{
// Get the value corresponding to key and store in var
// Return true if key is found
// Otherwise set var to given default
mapci p = myContents.find(key);
bool found = ( p != myContents.end() );
if( found )
var = string_as_T<T>( p->second );
else
var = value;
return found;
}
template<class T>
void ConfigFile::add( string key, const T& value )
{
// Add a key with given value
string v = T_as_string( value );
trim(key);
trim(v);
myContents[key] = v;
return;
}
#endif // CONFIGFILE_H
// Release notes:
// v1.0 21 May 1999
// + First release
// + Template read() access only through non-member readConfigFile()
// + ConfigurationFileBool is only built-in helper class
//
// v2.0 3 May 2002
// + Shortened name from ConfigurationFile to ConfigFile
// + Implemented template member functions
// + Changed default comment separator from % to #
// + Enabled reading of multiple-line values
//
// v2.1 24 May 2004
// + Made template specializations inline to avoid compiler-dependent linkage
// + Allowed comments within multiple-line values
// + Enabled blank line termination for multiple-line values
// + Added optional sentry to detect end of configuration file
// + Rewrote messy trimWhitespace() function as elegant trim()

360
3rdparty/libprojectm/FindPkgConfig.cmake vendored Normal file
View File

@ -0,0 +1,360 @@
# - a pkg-config module for CMake
#
# Usage:
# pkg_check_modules(<PREFIX> [REQUIRED] <MODULE> [<MODULE>]*)
# checks for all the given modules
#
# pkg_search_module(<PREFIX> [REQUIRED] <MODULE> [<MODULE>]*)
# checks for given modules and uses the first working one
#
# When the 'REQUIRED' argument was set, macros will fail with an error
# when module(s) could not be found
#
# It sets the following variables:
# PKG_CONFIG_FOUND ... true iff pkg-config works on the system
# PKG_CONFIG_EXECUTABLE ... pathname of the pkg-config program
# <PREFIX>_FOUND ... set to 1 iff module(s) exist
#
# For the following variables two sets of values exist; first one is the
# common one and has the given PREFIX. The second set contains flags
# which are given out when pkgconfig was called with the '--static'
# option.
# <XPREFIX>_LIBRARIES ... only the libraries (w/o the '-l')
# <XPREFIX>_LIBRARY_DIRS ... the paths of the libraries (w/o the '-L')
# <XPREFIX>_LDFLAGS ... all required linker flags
# <XPREFIX>_LDFLAGS_OTHERS ... all other linker flags
# <XPREFIX>_INCLUDE_DIRS ... the '-I' preprocessor flags (w/o the '-I')
# <XPREFIX>_CFLAGS ... all required cflags
# <XPREFIX>_CFLAGS_OTHERS ... the other compiler flags
#
# <XPREFIX> = <PREFIX> for common case
# <XPREFIX> = <PREFIX>_STATIC for static linking
#
# There are some special variables whose prefix depends on the count
# of given modules. When there is only one module, <PREFIX> stays
# unchanged. When there are multiple modules, the prefix will be
# changed to <PREFIX>_<MODNAME>:
# <XPREFIX>_VERSION ... version of the module
# <XPREFIX>_PREFIX ... prefix-directory of the module
# <XPREFIX>_INCLUDEDIR ... include-dir of the module
# <XPREFIX>_LIBDIR ... lib-dir of the module
#
# <XPREFIX> = <PREFIX> when |MODULES| == 1, else
# <XPREFIX> = <PREFIX>_<MODNAME>
#
# A <MODULE> parameter can have the following formats:
# {MODNAME} ... matches any version
# {MODNAME}>={VERSION} ... at least version <VERSION> is required
# {MODNAME}={VERSION} ... exactly version <VERSION> is required
# {MODNAME}<={VERSION} ... modules must not be newer than <VERSION>
#
# Examples
# pkg_check_modules (GLIB2 glib-2.0)
#
# pkg_check_modules (GLIB2 glib-2.0>=2.10)
# requires at least version 2.10 of glib2 and defines e.g.
# GLIB2_VERSION=2.10.3
#
# pkg_check_modules (FOO glib-2.0>=2.10 gtk+-2.0)
# requires both glib2 and gtk2, and defines e.g.
# FOO_glib-2.0_VERSION=2.10.3
# FOO_gtk+-2.0_VERSION=2.8.20
#
# pkg_check_modules (XRENDER REQUIRED xrender)
# defines e.g.:
# XRENDER_LIBRARIES=Xrender;X11
# XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp
#
# pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2)
# Copyright (C) 2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
#
# Redistribution and use, with or without modification, are permitted
# provided that the following conditions are met:
#
# 1. Redistributions must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. The name of the author may not be used to endorse or promote
# products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
### Common stuff ####
set(PKG_CONFIG_VERSION 1)
set(PKG_CONFIG_FOUND 0)
find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable")
mark_as_advanced(PKG_CONFIG_EXECUTABLE)
if(PKG_CONFIG_EXECUTABLE)
set(PKG_CONFIG_FOUND 1)
endif(PKG_CONFIG_EXECUTABLE)
# Unsets the given variables
macro(_pkgconfig_unset var)
set(${var} "" CACHE INTERNAL "")
endmacro(_pkgconfig_unset)
macro(_pkgconfig_set var value)
set(${var} ${value} CACHE INTERNAL "")
endmacro(_pkgconfig_set)
# Invokes pkgconfig, cleans up the result and sets variables
macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp)
set(_pkgconfig_invoke_result)
execute_process(
COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist}
OUTPUT_VARIABLE _pkgconfig_invoke_result
RESULT_VARIABLE _pkgconfig_failed)
if (_pkgconfig_failed)
set(_pkgconfig_${_varname} "")
_pkgconfig_unset(${_prefix}_${_varname})
else(_pkgconfig_failed)
string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
string(REGEX REPLACE " +$" "" _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
if (NOT ${_regexp} STREQUAL "")
string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
endif(NOT ${_regexp} STREQUAL "")
separate_arguments(_pkgconfig_invoke_result)
#message(STATUS " ${_varname} ... ${_pkgconfig_invoke_result}")
set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result})
_pkgconfig_set(${_prefix}_${_varname} "${_pkgconfig_invoke_result}")
endif(_pkgconfig_failed)
endmacro(_pkgconfig_invoke)
# Invokes pkgconfig two times; once without '--static' and once with
# '--static'
macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp)
_pkgconfig_invoke("${_pkglist}" ${_prefix} ${_varname} "${cleanup_regexp}" ${ARGN})
_pkgconfig_invoke("${_pkglist}" ${_prefix} STATIC_${_varname} "${cleanup_regexp}" --static ${ARGN})
endmacro(_pkgconfig_invoke_dyn)
# Splits given arguments into options and a package list
macro(_pkgconfig_parse_options _result _is_req)
set(${_is_req} 0)
foreach(_pkg ${ARGN})
if (_pkg STREQUAL "REQUIRED")
set(${_is_req} 1)
endif (_pkg STREQUAL "REQUIRED")
endforeach(_pkg ${ARGN})
set(${_result} ${ARGN})
list(REMOVE_ITEM ${_result} "REQUIRED")
endmacro(_pkgconfig_parse_options)
###
macro(_pkg_check_modules_internal _is_required _is_silent _prefix)
_pkgconfig_unset(${_prefix}_FOUND)
_pkgconfig_unset(${_prefix}_VERSION)
_pkgconfig_unset(${_prefix}_PREFIX)
_pkgconfig_unset(${_prefix}_INCLUDEDIR)
_pkgconfig_unset(${_prefix}_LIBDIR)
_pkgconfig_unset(${_prefix}_LIBS)
_pkgconfig_unset(${_prefix}_LIBS_L)
_pkgconfig_unset(${_prefix}_LIBS_PATHS)
_pkgconfig_unset(${_prefix}_LIBS_OTHER)
_pkgconfig_unset(${_prefix}_CFLAGS)
_pkgconfig_unset(${_prefix}_CFLAGS_I)
_pkgconfig_unset(${_prefix}_CFLAGS_OTHER)
_pkgconfig_unset(${_prefix}_STATIC_LIBDIR)
_pkgconfig_unset(${_prefix}_STATIC_LIBS)
_pkgconfig_unset(${_prefix}_STATIC_LIBS_L)
_pkgconfig_unset(${_prefix}_STATIC_LIBS_PATHS)
_pkgconfig_unset(${_prefix}_STATIC_LIBS_OTHER)
_pkgconfig_unset(${_prefix}_STATIC_CFLAGS)
_pkgconfig_unset(${_prefix}_STATIC_CFLAGS_I)
_pkgconfig_unset(${_prefix}_STATIC_CFLAGS_OTHER)
# create a better addressable variable of the modules and calculate its size
set(_pkg_check_modules_list ${ARGN})
list(LENGTH _pkg_check_modules_list _pkg_check_modules_cnt)
if(PKG_CONFIG_EXECUTABLE)
# give out status message telling checked module
if (NOT ${_is_silent})
if (_pkg_check_modules_cnt EQUAL 1)
message(STATUS "checking for module '${_pkg_check_modules_list}'")
else(_pkg_check_modules_cnt EQUAL 1)
message(STATUS "checking for modules '${_pkg_check_modules_list}'")
endif(_pkg_check_modules_cnt EQUAL 1)
endif(NOT ${_is_silent})
set(_pkg_check_modules_packages)
set(_pkg_check_modules_failed)
# iterate through module list and check whether they exist and match the required version
foreach (_pkg_check_modules_pkg ${_pkg_check_modules_list})
set(_pkg_check_modules_exist_query)
# check whether version is given
if (_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*")
string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\1" _pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}")
string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\2" _pkg_check_modules_pkg_op "${_pkg_check_modules_pkg}")
string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\3" _pkg_check_modules_pkg_ver "${_pkg_check_modules_pkg}")
else(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*")
set(_pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}")
set(_pkg_check_modules_pkg_op)
set(_pkg_check_modules_pkg_ver)
endif(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*")
# handle the operands
if (_pkg_check_modules_pkg_op STREQUAL ">=")
list(APPEND _pkg_check_modules_exist_query --atleast-version)
endif(_pkg_check_modules_pkg_op STREQUAL ">=")
if (_pkg_check_modules_pkg_op STREQUAL "=")
list(APPEND _pkg_check_modules_exist_query --exact-version)
endif(_pkg_check_modules_pkg_op STREQUAL "=")
if (_pkg_check_modules_pkg_op STREQUAL "<=")
list(APPEND _pkg_check_modules_exist_query --max-version)
endif(_pkg_check_modules_pkg_op STREQUAL "<=")
# create the final query which is of the format:
# * --atleast-version <version> <pkg-name>
# * --exact-version <version> <pkg-name>
# * --max-version <version> <pkg-name>
# * --exists <pkg-name>
if (_pkg_check_modules_pkg_op)
list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}")
else(_pkg_check_modules_pkg_op)
list(APPEND _pkg_check_modules_exist_query --exists)
endif(_pkg_check_modules_pkg_op)
_pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION)
_pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX)
_pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR)
_pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR)
list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}")
list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}")
# execute the query
execute_process(
COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query}
RESULT_VARIABLE _pkgconfig_retval)
# evaluate result and tell failures
if (_pkgconfig_retval)
if(NOT ${_is_silent})
message(STATUS " package '${_pkg_check_modules_pkg}' not found")
endif(NOT ${_is_silent})
set(_pkg_check_modules_failed 1)
endif(_pkgconfig_retval)
endforeach(_pkg_check_modules_pkg)
if(_pkg_check_modules_failed)
# fail when requested
if (${_is_required})
message(SEND_ERROR "A required package was not found")
endif (${_is_required})
else(_pkg_check_modules_failed)
# when we are here, we checked whether requested modules
# exist. Now, go through them and set variables
_pkgconfig_set(${_prefix}_FOUND 1)
list(LENGTH _pkg_check_modules_packages pkg_count)
# iterate through all modules again and set individual variables
foreach (_pkg_check_modules_pkg ${_pkg_check_modules_packages})
# handle case when there is only one package required
if (pkg_count EQUAL 1)
set(_pkg_check_prefix "${_prefix}")
else(pkg_count EQUAL 1)
set(_pkg_check_prefix "${_prefix}_${_pkg_check_modules_pkg}")
endif(pkg_count EQUAL 1)
_pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" VERSION "" --modversion )
_pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" PREFIX "" --variable=prefix )
_pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" INCLUDEDIR "" --variable=includedir )
_pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" LIBDIR "" --variable=libdir )
message(STATUS " found ${_pkg_check_modules_pkg}, version ${_pkgconfig_VERSION}")
endforeach(_pkg_check_modules_pkg)
# set variables which are combined for multiple modules
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARIES "(^| )-l" --libs-only-l )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARY_DIRS "(^| )-L" --libs-only-L )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS "" --libs )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER "" --libs-only-other )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS "(^| )-I" --cflags-only-I )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags )
_pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other )
endif(_pkg_check_modules_failed)
else(PKG_CONFIG_EXECUTABLE)
if (${_is_required})
message(SEND_ERROR "pkg-config tool not found")
endif (${_is_required})
endif(PKG_CONFIG_EXECUTABLE)
endmacro(_pkg_check_modules_internal)
###
### User visible macros start here
###
###
macro(pkg_check_modules _prefix _module0)
# check cached value
if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})
_pkgconfig_parse_options (_pkg_modules _pkg_is_required "${_module0}" ${ARGN})
_pkg_check_modules_internal("${_pkg_is_required}" 0 "${_prefix}" ${_pkg_modules})
_pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})
endmacro(pkg_check_modules)
###
macro(pkg_search_module _prefix _module0)
# check cached value
if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})
set(_pkg_modules_found 0)
_pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required "${_module0}" ${ARGN})
message(STATUS "checking for one of the modules '${_pkg_modules_alt}'")
# iterate through all modules and stop at the first working one.
foreach(_pkg_alt ${_pkg_modules_alt})
if(NOT _pkg_modules_found)
_pkg_check_modules_internal(0 1 "${_prefix}" "${_pkg_alt}")
endif(NOT _pkg_modules_found)
if (${_prefix}_FOUND)
set(_pkg_modules_found 1)
endif(${_prefix}_FOUND)
endforeach(_pkg_alt)
if (NOT ${_prefix}_FOUND)
if(${_pkg_is_required})
message(SEND_ERROR "None of the required '${_pkg_modules_alt}' found")
endif(${_pkg_is_required})
endif(NOT ${_prefix}_FOUND)
_pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION})
endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION})
endmacro(pkg_search_module)
### Local Variables:
### mode: cmake
### End:

192
3rdparty/libprojectm/HungarianMethod.hpp vendored Normal file
View File

@ -0,0 +1,192 @@
#ifndef HUNGARIAN_METHOD_HPP
#define HUNGARIAN_METHOD_HPP
//#include "Common.hpp"
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <limits>
/// A function object which calculates the maximum-weighted bipartite matching between
/// two sets via the hungarian method.
template <int N=20>
class HungarianMethod {
public :
static const int MAX_SIZE = N;
private:
int n, max_match; //n workers and n jobs
double lx[N], ly[N]; //labels of X and Y parts
int xy[N]; //xy[x] - vertex that is matched with x,
int yx[N]; //yx[y] - vertex that is matched with y
bool S[N], T[N]; //sets S and T in algorithm
double slack[N]; //as in the algorithm description
double slackx[N]; //slackx[y] such a vertex, that
// l(slackx[y]) + l(y) - w(slackx[y],y) = slack[y]
int prev[N]; //array for memorizing alternating paths
void init_labels(const double cost[N][N])
{
memset(lx, 0, sizeof(lx));
memset(ly, 0, sizeof(ly));
for (int x = 0; x < n; x++)
for (int y = 0; y < n; y++)
lx[x] = std::max(lx[x], cost[x][y]);
}
void augment(const double cost[N][N]) //main function of the algorithm
{
if (max_match == n) return; //check wether matching is already perfect
int x, y, root; //just counters and root vertex
int q[N], wr = 0, rd = 0; //q - queue for bfs, wr,rd - write and read
//pos in queue
memset(S, false, sizeof(S)); //init set S
memset(T, false, sizeof(T)); //init set T
memset(prev, -1, sizeof(prev)); //init set prev - for the alternating tree
for (x = 0; x < n; x++) //finding root of the tree
if (xy[x] == -1)
{
q[wr++] = root = x;
prev[x] = -2;
S[x] = true;
break;
}
for (y = 0; y < n; y++) //initializing slack array
{
slack[y] = lx[root] + ly[y] - cost[root][y];
slackx[y] = root;
}
while (true) //main cycle
{
while (rd < wr) //building tree with bfs cycle
{
x = q[rd++]; //current vertex from X part
for (y = 0; y < n; y++) //iterate through all edges in equality graph
if (cost[x][y] == lx[x] + ly[y] && !T[y])
{
if (yx[y] == -1) break; //an exposed vertex in Y found, so
//augmenting path exists!
T[y] = true; //else just add y to T,
q[wr++] = yx[y]; //add vertex yx[y], which is matched
//with y, to the queue
add_to_tree(yx[y], x, cost); //add edges (x,y) and (y,yx[y]) to the tree
}
if (y < n) break; //augmenting path found!
}
if (y < n) break; //augmenting path found!
update_labels(); //augmenting path not found, so improve labeling
wr = rd = 0;
for (y = 0; y < n; y++)
//in this cycle we add edges that were added to the equality graph as a
//result of improving the labeling, we add edge (slackx[y], y) to the tree if
//and only if !T[y] && slack[y] == 0, also with this edge we add another one
//(y, yx[y]) or augment the matching, if y was exposed
if (!T[y] && slack[y] == 0)
{
if (yx[y] == -1) //exposed vertex in Y found - augmenting path exists!
{
x = slackx[y];
break;
}
else
{
T[y] = true; //else just add y to T,
if (!S[yx[y]])
{
q[wr++] = yx[y]; //add vertex yx[y], which is matched with
//y, to the queue
add_to_tree(yx[y], slackx[y],cost); //and add edges (x,y) and (y,
//yx[y]) to the tree
}
}
}
if (y < n) break; //augmenting path found!
}
if (y < n) //we found augmenting path!
{
max_match++; //increment matching
//in this cycle we inverse edges along augmenting path
for (int cx = x, cy = y, ty; cx != -2; cx = prev[cx], cy = ty)
{
ty = xy[cx];
yx[cy] = cx;
xy[cx] = cy;
}
augment(cost); //recall function, go to step 1 of the algorithm
}
}//end of augment() function
void update_labels()
{
int x, y;
double delta = std::numeric_limits<double>::max();
for (y = 0; y < n; y++) //calculate delta using slack
if (!T[y])
delta = std::min(delta, slack[y]);
for (x = 0; x < n; x++) //update X labels
if (S[x]) lx[x] -= delta;
for (y = 0; y < n; y++) //update Y labels
if (T[y]) ly[y] += delta;
for (y = 0; y < n; y++) //update slack array
if (!T[y])
slack[y] -= delta;
}
void add_to_tree(int x, int prevx, const double cost[N][N])
//x - current vertex,prevx - vertex from X before x in the alternating path,
//so we add edges (prevx, xy[x]), (xy[x], x)
{
S[x] = true; //add x to S
prev[x] = prevx; //we need this when augmenting
for (int y = 0; y < n; y++) //update slacks, because we add new vertex to S
if (lx[x] + ly[y] - cost[x][y] < slack[y])
{
slack[y] = lx[x] + ly[y] - cost[x][y];
slackx[y] = x;
}
}
public:
/// Computes the best matching of two sets given its cost matrix.
/// See the matching() method to get the computed match result.
/// \param cost a matrix of two sets I,J where cost[i][j] is the weight of edge i->j
/// \param logicalSize the number of elements in both I and J
/// \returns the total cost of the best matching
inline double operator()(const double cost[N][N], int logicalSize)
{
n = logicalSize;
assert(n <= N);
double ret = 0; //weight of the optimal matching
max_match = 0; //number of vertices in current matching
memset(xy, -1, sizeof(xy));
memset(yx, -1, sizeof(yx));
init_labels(cost); //step 0
augment(cost); //steps 1-3
for (int x = 0; x < n; x++) //forming answer there
ret += cost[x][xy[x]];
return ret;
}
/// Gets the matching element in 2nd set of the ith element in the first set
/// \param i the index of the ith element in the first set (passed in operator())
/// \returns an index j, denoting the matched jth element of the 2nd set
inline int matching(int i) const {
return xy[i];
}
/// Gets the matching element in 1st set of the jth element in the 2nd set
/// \param j the index of the jth element in the 2nd set (passed in operator())
/// \returns an index i, denoting the matched ith element of the 1st set
/// \note inverseMatching(matching(i)) == i
inline int inverseMatching(int j) const {
return yx[j];
}
};
#endif

5985
3rdparty/libprojectm/IdleTextures.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

220
3rdparty/libprojectm/KeyHandler.cpp vendored Executable file
View File

@ -0,0 +1,220 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <stdio.h>
#include "Common.hpp"
#include "fatal.h"
#include "KeyHandler.hpp"
#include "event.h"
#include "BeatDetect.hpp"
#include "PresetChooser.hpp"
#include "Renderer.hpp"
#include "projectM.hpp"
#include <iostream>
#include "TimeKeeper.hpp"
class Preset;
interface_t current_interface = DEFAULT_INTERFACE;
void selectRandom(const bool hardCut);
void selectNext(const bool hardCut);
void selectPrevious(const bool hardCut);
void refreshConsole() {
switch (current_interface) {
case MENU_INTERFACE:
// unimplemented
break;
case SHELL_INTERFACE:
// unimplemented
break;
case EDITOR_INTERFACE:
// unimplemented
break;
case DEFAULT_INTERFACE:
break;
case BROWSER_INTERFACE:
// unimplemented
break;
default:
break;
}
}
void projectM::key_handler( projectMEvent event,
projectMKeycode keycode, projectMModifier modifier ) {
switch( event ) {
case PROJECTM_KEYDOWN:
//default_key_handler();
switch (current_interface)
{
case MENU_INTERFACE:
// menu_key_handler(this, event, keycode);
break;
case SHELL_INTERFACE:
//shell_key_handler();
break;
case EDITOR_INTERFACE:
// editor_key_handler(event,keycode);
break;
case BROWSER_INTERFACE:
// browser_key_handler(event,keycode,modifier);
break;
case DEFAULT_INTERFACE:
default_key_handler(event,keycode);
break;
default:
default_key_handler(event,keycode);
break;
}
break;
default:
break;
}
}
void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode) {
switch( event ) {
case PROJECTM_KEYDOWN:
switch( keycode )
{
case PROJECTM_K_UP:
beatDetect->beat_sensitivity += 0.25;
if (beatDetect->beat_sensitivity > 5.0) beatDetect->beat_sensitivity = 5.0;
break;
case PROJECTM_K_DOWN:
beatDetect->beat_sensitivity -= 0.25;
if (beatDetect->beat_sensitivity < 0) beatDetect->beat_sensitivity = 0;
break;
case PROJECTM_K_h:
renderer->showhelp = !renderer->showhelp;
renderer->showstats= false;
renderer->showfps=false;
case PROJECTM_K_F1:
renderer->showhelp = !renderer->showhelp;
renderer->showstats=false;
renderer->showfps=false;
break;
case PROJECTM_K_y:
this->setShuffleEnabled(!this->isShuffleEnabled());
break;
case PROJECTM_K_F5:
if (!renderer->showhelp)
renderer->showfps = !renderer->showfps;
break;
case PROJECTM_K_F4:
if (!renderer->showhelp)
renderer->showstats = !renderer->showstats;
break;
case PROJECTM_K_F3: {
renderer->showpreset = !renderer->showpreset;
break;
}
case PROJECTM_K_F2:
renderer->showtitle = !renderer->showtitle;
break;
#ifndef MACOS
case PROJECTM_K_F9:
#else
case PROJECTM_K_F8:
#endif
renderer->studio = !renderer->studio;
break;
case PROJECTM_K_ESCAPE: {
// exit( 1 );
break;
}
case PROJECTM_K_f:
break;
case PROJECTM_K_a:
renderer->correction = !renderer->correction;
break;
case PROJECTM_K_b:
break;
case PROJECTM_K_n:
selectNext(true);
break;
case PROJECTM_K_N:
selectNext(false);
break;
case PROJECTM_K_r:
selectRandom(true);
break;
case PROJECTM_K_R:
selectRandom(false);
break;
case PROJECTM_K_p:
selectPrevious(true);
break;
case PROJECTM_K_P:
selectPrevious(false);
break;
case PROJECTM_K_l:
renderer->noSwitch=!renderer->noSwitch;
break;
case PROJECTM_K_s:
renderer->studio = !renderer->studio;
case PROJECTM_K_i:
break;
case PROJECTM_K_z:
break;
case PROJECTM_K_0:
// nWaveMode=0;
break;
case PROJECTM_K_6:
// nWaveMode=6;
break;
case PROJECTM_K_7:
// nWaveMode=7;
break;
case PROJECTM_K_m:
break;
case PROJECTM_K_t:
break;
default:
break;
}
default:
break;
}
}

39
3rdparty/libprojectm/KeyHandler.hpp vendored Executable file
View File

@ -0,0 +1,39 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id: console_interface.h,v 1.1.1.1 2005/12/23 18:05:03 psperl Exp $
*
* $Log$
*/
#ifndef _KEY_HANDLER_HPP
#define _KEY_HANDLER_HPP
#include "event.h"
class projectM;
void default_key_handler(projectM *PM, projectMEvent event, projectMKeycode keycode);
void refreshConsole();
#if defined(__CPLUSPLUS) && !defined(MACOS)
extern "C" void key_handler(projectM *PM, projectMEvent event, projectMKeycode keycode, projectMModifier modifier );
#else
extern void key_handler(projectM *PM, projectMEvent event, projectMKeycode keycode, projectMModifier modifier );
#endif
#endif /** !_KEY_HANDLER_HPP */

View File

@ -0,0 +1,157 @@
//
// C++ Implementation: BuiltinFuncs
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
/* Loads all builtin functions */
/* Loads a builtin function */
#include "BuiltinFuncs.hpp"
#include <string>
#include <iostream>
#include "fatal.h"
std::map<std::string, Func*> BuiltinFuncs::builtin_func_tree;
int BuiltinFuncs::load_builtin_func(const std::string & name, float (*func_ptr)(float*), int num_args) {
Func * func;
int retval;
/* Create new function */
func = new Func(name, func_ptr, num_args);
if (func == NULL)
return PROJECTM_OUTOFMEM_ERROR;
retval = insert_func( func );
return retval;
}
Func * BuiltinFuncs::find_func(const std::string & name) {
std::map<std::string, Func*>::iterator pos = builtin_func_tree.find(name);
// Case: function not found, return null
if (pos == builtin_func_tree.end())
return 0;
// Case: function found, return a pointer to it
return pos->second;
}
int BuiltinFuncs::load_all_builtin_func() {
if (load_builtin_func("int", FuncWrappers::int_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("abs", FuncWrappers::abs_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("sin", FuncWrappers::sin_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("cos", FuncWrappers::cos_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("tan", FuncWrappers::tan_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("asin", FuncWrappers::asin_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("acos", FuncWrappers::acos_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("atan", FuncWrappers::atan_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("sqr", FuncWrappers::sqr_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("sqrt", FuncWrappers::sqrt_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("pow", FuncWrappers::pow_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("exp", FuncWrappers::exp_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("log", FuncWrappers::log_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("log10", FuncWrappers::log10_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("sign", FuncWrappers::sign_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("min", FuncWrappers::min_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("max", FuncWrappers::max_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("sigmoid", FuncWrappers::sigmoid_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("atan2", FuncWrappers::atan2_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("rand", FuncWrappers::rand_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("band", FuncWrappers::band_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("bor", FuncWrappers::bor_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("bnot", FuncWrappers::bnot_wrapper, 1) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("if", FuncWrappers::if_wrapper, 3) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("equal", FuncWrappers::equal_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("above", FuncWrappers::above_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("below", FuncWrappers::below_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("nchoosek", FuncWrappers::nchoosek_wrapper, 2) < 0)
return PROJECTM_ERROR;
if (load_builtin_func("fact", FuncWrappers::fact_wrapper, 1) < 0)
return PROJECTM_ERROR;
return PROJECTM_SUCCESS;
}
/* Initialize the builtin function database.
Should only be necessary once */
int BuiltinFuncs::init_builtin_func_db() {
int retval;
retval = load_all_builtin_func();
return retval;
}
/* Destroy the builtin function database.
Generally, do this on projectm exit */
int BuiltinFuncs::destroy_builtin_func_db() {
traverse<TraverseFunctors::Delete<Func> >(builtin_func_tree);
builtin_func_tree.clear();
return PROJECTM_SUCCESS;
}
/* Insert a function into the database */
int BuiltinFuncs::insert_func( Func *func ) {
assert(func);
std::pair<std::map<std::string, Func*>::iterator, bool> inserteePair =
builtin_func_tree.insert(std::make_pair(std::string(func->getName()), func));
if (!inserteePair.second) {
std::cerr << "Failed to insert builtin function \"" << func->getName() << "\" into collection! Bailing..." << std::endl;
abort();
}
return PROJECTM_SUCCESS;
}

View File

@ -0,0 +1,234 @@
//
// C++ Interface: BuiltinFuncs
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef _BUILTIN_FUNCS_HPP
#define _BUILTIN_FUNCS_HPP
#include "Common.hpp"
#include "Func.hpp"
#include <cmath>
#include <cstdlib>
#include <cassert>
#include "RandomNumberGenerators.hpp"
/* Wrappers for all the builtin functions
The arg_list pointer is a list of floats. Its
size is equal to the number of arguments the parameter
takes */
class FuncWrappers {
/* Values to optimize the sigmoid function */
static const int R = 32767;
static const int RR = 65534;
public:
static inline float int_wrapper(float * arg_list) {
return floor(arg_list[0]);
}
static inline float sqr_wrapper(float * arg_list) {
return pow(2, arg_list[0]);
}
static inline float sign_wrapper(float * arg_list) {
return -arg_list[0];
}
static inline float min_wrapper(float * arg_list) {
if (arg_list[0] > arg_list[1])
return arg_list[1];
return arg_list[0];
}
static inline float max_wrapper(float * arg_list) {
if (arg_list[0] > arg_list[1])
return arg_list[0];
return arg_list[1];
}
/* consult your AI book */
static inline float sigmoid_wrapper(float * arg_list) {
return (RR / (1 + exp( -(((float)(arg_list[0])) * arg_list[1]) / R) - R));
}
static inline float bor_wrapper(float * arg_list) {
return (float)((int)arg_list[0] || (int)arg_list[1]);
}
static inline float band_wrapper(float * arg_list) {
return (float)((int)arg_list[0] && (int)arg_list[1]);
}
static inline float bnot_wrapper(float * arg_list) {
return (float)(!(int)arg_list[0]);
}
static inline float if_wrapper(float * arg_list) {
if ((int)arg_list[0] == 0)
return arg_list[2];
return arg_list[1];
}
static inline float rand_wrapper(float * arg_list) {
float l=1;
// printf("RAND ARG:(%d)\n", (int)arg_list[0]);
if ((int)arg_list[0] > 0)
l = (float) RandomNumberGenerators::uniformInteger((int)arg_list[0]);
return l;
}
static inline float equal_wrapper(float * arg_list) {
return (arg_list[0] == arg_list[1]);
}
static inline float above_wrapper(float * arg_list) {
return (arg_list[0] > arg_list[1]);
}
static inline float below_wrapper(float * arg_list) {
return (arg_list[0] < arg_list[1]);
}
static float sin_wrapper(float * arg_list) {
assert(arg_list);
//return .5;
float d = sinf(*arg_list);
return d;
//return (sin (arg_list[0]));
}
static inline float cos_wrapper(float * arg_list) {
return (cos (arg_list[0]));
}
static inline float tan_wrapper(float * arg_list) {
return (tan(arg_list[0]));
}
static inline float asin_wrapper(float * arg_list) {
return (asin (arg_list[0]));
}
static inline float acos_wrapper(float * arg_list) {
return (acos (arg_list[0]));
}
static inline float atan_wrapper(float * arg_list) {
return (atan (arg_list[0]));
}
static inline float atan2_wrapper(float * arg_list) {
return (atan2 (arg_list[0], arg_list[1]));
}
static inline float pow_wrapper(float * arg_list) {
return (pow (arg_list[0], arg_list[1]));
}
static inline float exp_wrapper(float * arg_list) {
return (exp(arg_list[0]));
}
static inline float abs_wrapper(float * arg_list) {
return (fabs(arg_list[0]));
}
static inline float log_wrapper(float* arg_list) {
return (log (arg_list[0]));
}
static inline float log10_wrapper(float * arg_list) {
return (log10 (arg_list[0]));
}
static inline float sqrt_wrapper(float * arg_list) {
return (sqrt (arg_list[0]));
}
static inline float nchoosek_wrapper(float * arg_list) {
unsigned long cnm = 1UL;
int i, f;
int n, m;
n = (int)arg_list[0];
m = (int)arg_list[1];
if (m*2 >n) m = n-m;
for (i=1 ; i <= m; n--, i++)
{
if ((f=n) % i == 0)
f /= i;
else cnm /= i;
cnm *= f;
}
return (float)cnm;
}
static inline float fact_wrapper(float * arg_list) {
int result = 1;
int n = (int)arg_list[0];
while (n > 1) {
result = result * n;
n--;
}
return (float)result;
}
};
#include <map>
class BuiltinFuncs {
public:
static int init_builtin_func_db();
static int destroy_builtin_func_db();
static int load_all_builtin_func();
static int load_builtin_func( const std::string & name, float (*func_ptr)(float*), int num_args );
static int insert_func( Func *func );
static int remove_func( Func *func );
static Func *find_func( const std::string & name );
private:
static std::map<std::string, Func*> builtin_func_tree;
};
#endif

View File

@ -0,0 +1,411 @@
#include "fatal.h"
#include "BuiltinParams.hpp"
#include <cassert>
#include <iostream>
#include <algorithm>
#include "InitCondUtils.hpp"
#include <sstream>
#include <stdio.h>
#include "Common.hpp"
BuiltinParams::BuiltinParams() {}
BuiltinParams::BuiltinParams(PresetInputs & presetInputs, PresetOutputs & presetOutputs)
{
presetInputs.Initialize(presetOutputs.gx, presetOutputs.gy);
int ret;
if ((ret = init_builtin_param_db(presetInputs, presetOutputs)) != PROJECTM_SUCCESS)
{
std::cout << "failed to allocate builtin parameter database with error " << ret << std::endl;;
throw ret;
}
}
BuiltinParams::~BuiltinParams()
{
destroy_builtin_param_db();
}
/* Loads a float parameter into the builtin database */
int BuiltinParams::load_builtin_param_float(const std::string & name, void * engine_val, void * matrix, short int flags,
float init_val, float upper_bound, float lower_bound, const std::string & alt_name)
{
Param * param = NULL;
CValue iv, ub, lb;
iv.float_val = init_val;
ub.float_val = upper_bound;
lb.float_val = lower_bound;
/* Create new parameter of type float */
if (BUILTIN_PARAMS_DEBUG == 2)
{
printf("load_builtin_param_float: (name \"%s\") (alt_name = \"%s\") ", name.c_str(), alt_name.c_str());
fflush(stdout);
}
std::string lowerName(name);
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
if ((param = new Param(lowerName, P_TYPE_DOUBLE, flags, engine_val, matrix, iv, ub, lb)) == NULL)
{
return PROJECTM_OUTOFMEM_ERROR;
}
if (BUILTIN_PARAMS_DEBUG == 2)
{
printf("created...");
fflush(stdout);
}
/* Insert the paremeter into the database */
if (insert_builtin_param( param ) < 0)
{
delete param;
return PROJECTM_ERROR;
}
if (BUILTIN_PARAMS_DEBUG == 2)
{
printf("inserted...");
fflush(stdout);
}
/* If this parameter has an alternate name, insert it into the database as link */
if (alt_name != "")
{
std::string alt_lower_name(alt_name);
std::transform(alt_lower_name.begin(), alt_lower_name.end(), alt_lower_name.begin(), tolower);
insert_param_alt_name(param,alt_lower_name);
if (BUILTIN_PARAMS_DEBUG == 2)
{
printf("alt_name inserted...");
fflush(stdout);
}
}
if (BUILTIN_PARAMS_DEBUG == 2) printf("finished\n");
/* Finished, return success */
return PROJECTM_SUCCESS;
}
/* Destroy the builtin parameter database.
Generally, do this on projectm exit */
int BuiltinParams::destroy_builtin_param_db()
{
traverse<TraverseFunctors::Delete<Param> >(builtin_param_tree);
return PROJECTM_SUCCESS;
}
/* Insert a parameter into the database with an alternate name */
int BuiltinParams::insert_param_alt_name(Param * param, const std::string & alt_name)
{
assert(param);
aliasMap.insert(std::make_pair(alt_name, param->name));
return PROJECTM_SUCCESS;
}
Param * BuiltinParams::find_builtin_param(const std::string & name)
{
AliasMap::iterator pos = aliasMap.find(name);
Param * param = 0;
//std::cerr << "[BuiltinParams] find_builtin_param: name is " << name << std::endl;
if (pos == aliasMap.end())
{
std::map<std::string, Param*>::iterator builtinPos = builtin_param_tree.find(name);
if (builtinPos != builtin_param_tree.end()) {
// std::cerr << "[BuiltinParams] find_builtin_param: found it directly." << std::endl;
param = builtinPos->second;
}
}
else
{
std::map<std::string, Param*>::iterator builtinPos = builtin_param_tree.find(pos->second);
if (builtinPos != builtin_param_tree.end()) {
//std::cerr << "[BuiltinParams] find_builtin_param: found it indirectly." << std::endl;
param = builtinPos->second;
}
}
return param;
}
/* Loads a integer parameter into the builtin database */
int BuiltinParams::load_builtin_param_int(const std::string & name, void * engine_val, short int flags,
int init_val, int upper_bound, int lower_bound, const std::string &alt_name)
{
Param * param;
CValue iv, ub, lb;
iv.int_val = init_val;
ub.int_val = upper_bound;
lb.int_val = lower_bound;
// normalize to lower case as milkdrop scripts depend on this
std::string lowerName(name);
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
param = new Param(lowerName, P_TYPE_INT, flags, engine_val, NULL, iv, ub, lb);
if (param == NULL)
{
return PROJECTM_OUTOFMEM_ERROR;
}
if (insert_builtin_param( param ) < 0)
{
delete param;
return PROJECTM_ERROR;
}
if (alt_name != "")
{
std::string alt_lower_name(alt_name);
std::transform(alt_lower_name.begin(), alt_lower_name.end(), alt_lower_name.begin(), tolower);
insert_param_alt_name(param,alt_lower_name);
}
return PROJECTM_SUCCESS;
}
int BuiltinParams::load_builtin_param_string( const std::string & name, std::string * engine_val, short int flags) {
/* Creates a new parameter of type string */
Param * param = Param::new_param_string(name.c_str(), flags, engine_val);
if (insert_builtin_param( param ) < 0)
{
delete param;
return PROJECTM_ERROR;
}
return PROJECTM_SUCCESS;
}
/* Loads a boolean parameter */
int BuiltinParams::load_builtin_param_bool(const std:: string & name, void * engine_val, short int flags,
int init_val, const std::string &alt_name)
{
Param * param;
CValue iv, ub, lb;
iv.int_val = init_val;
ub.int_val = TRUE;
lb.int_val = false;
std::string lowerName(name);
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
param = new Param(lowerName, P_TYPE_BOOL, flags, engine_val, NULL, iv, ub, lb);
if (param == NULL)
{
return PROJECTM_OUTOFMEM_ERROR;
}
if (insert_builtin_param(param) < 0)
{
delete param;
return PROJECTM_ERROR;
}
if (alt_name != "")
{
std::string alt_lower_name(alt_name);
std::transform(alt_lower_name.begin(), alt_lower_name.end(), alt_lower_name.begin(), tolower);
insert_param_alt_name(param,alt_lower_name);
}
return PROJECTM_SUCCESS;
}
/* Inserts a parameter into the builtin database */
int BuiltinParams::insert_builtin_param( Param *param )
{
std::pair<std::map<std::string, Param*>::iterator, bool> inserteePos = builtin_param_tree.insert(std::make_pair(param->name, param));
return inserteePos.second;
}
/* Initialize the builtin parameter database.
Should only be necessary once */
int BuiltinParams::init_builtin_param_db(const PresetInputs & presetInputs, PresetOutputs & presetOutputs)
{
if (BUILTIN_PARAMS_DEBUG)
{
printf("init_builtin_param: loading database...");
fflush(stdout);
}
/* Loads all builtin parameters into the database */
if (load_all_builtin_param(presetInputs, presetOutputs) < 0)
{
if (BUILTIN_PARAMS_DEBUG) printf("failed loading builtin parameters (FATAL)\n");
return PROJECTM_ERROR;
}
if (BUILTIN_PARAMS_DEBUG) printf("success!\n");
/* Finished, no errors */
return PROJECTM_SUCCESS;
}
/* Loads all builtin parameters, limits are also defined here */
int BuiltinParams::load_all_builtin_param(const PresetInputs & presetInputs, PresetOutputs & presetOutputs)
{
load_builtin_param_float("frating", (void*)&presetOutputs.fRating, NULL, P_FLAG_NONE, 0.0 , 5.0, 0.0, "");
load_builtin_param_float("fwavescale", (void*)&presetOutputs.wave.scale, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, "");
load_builtin_param_float("gamma", (void*)&presetOutputs.fGammaAdj, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "fGammaAdj");
load_builtin_param_float("echo_zoom", (void*)&presetOutputs.videoEcho.zoom, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "fVideoEchoZoom");
load_builtin_param_float("echo_alpha", (void*)&presetOutputs.videoEcho.a, NULL, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "fvideoechoalpha");
load_builtin_param_float("wave_a", (void*)&presetOutputs.wave.a, NULL, P_FLAG_NONE, 0.0, 1.0, 0, "fwavealpha");
load_builtin_param_float("fwavesmoothing", (void*)&presetOutputs.wave.smoothing, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "");
load_builtin_param_float("fmodwavealphastart", (void*)&presetOutputs.wave.modOpacityStart, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "");
load_builtin_param_float("fmodwavealphaend", (void*)&presetOutputs.wave.modOpacityEnd, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "");
load_builtin_param_float("fWarpAnimSpeed", (void*)&presetOutputs.fWarpAnimSpeed, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "");
load_builtin_param_float("fWarpScale", (void*)&presetOutputs.fWarpScale, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "");
// load_builtin_param_float("warp", (void*)&presetOutputs.warp, warp_mesh, P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, 0, "");
load_builtin_param_float("fshader", (void*)&presetOutputs.fShader, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "");
load_builtin_param_float("decay", (void*)&presetOutputs.screenDecay, NULL, P_FLAG_NONE, 0.0, 1.0, 0, "fdecay");
load_builtin_param_int("echo_orient", (void*)&presetOutputs.videoEcho.orientation, P_FLAG_NONE, 0, 3, 0, "nVideoEchoOrientation");
load_builtin_param_int("wave_mode", (void*)&presetOutputs.wave.mode, P_FLAG_NONE, 0, 7, 0, "nwavemode");
load_builtin_param_bool("wave_additive", (void*)&presetOutputs.wave.additive, P_FLAG_NONE, false, "bAdditiveWaves");
load_builtin_param_bool("bmodwavealphabyvolume", (void*)&presetOutputs.wave.modulateAlphaByVolume, P_FLAG_NONE, false, "");
load_builtin_param_bool("wave_brighten", (void*)&presetOutputs.wave.maximizeColors, P_FLAG_NONE, false, "bMaximizeWaveColor");
load_builtin_param_bool("wrap", (void*)&presetOutputs.textureWrap, P_FLAG_NONE, false, "btexwrap");
load_builtin_param_bool("darken_center", (void*)&presetOutputs.bDarkenCenter, P_FLAG_NONE, false, "bdarkencenter");
load_builtin_param_bool("bredbluestereo", (void*)&presetOutputs.bRedBlueStereo, P_FLAG_NONE, false, "");
load_builtin_param_bool("brighten", (void*)&presetOutputs.bBrighten, P_FLAG_NONE, false, "bbrighten");
load_builtin_param_bool("darken", (void*)&presetOutputs.bDarken, P_FLAG_NONE, false, "bdarken");
load_builtin_param_bool("solarize", (void*)&presetOutputs.bSolarize, P_FLAG_NONE, false, "bsolarize");
load_builtin_param_bool("invert", (void*)&presetOutputs.bInvert, P_FLAG_NONE, false, "binvert");
load_builtin_param_bool("bmotionvectorson", (void*)&presetOutputs.bMotionVectorsOn, P_FLAG_NONE, false, "");
load_builtin_param_bool("wave_dots", (void*)&presetOutputs.wave.dots, P_FLAG_NONE, false, "bwavedots");
load_builtin_param_bool("wave_thick", (void*)&presetOutputs.wave.thick, P_FLAG_NONE, false, "bwavethick");
load_builtin_param_float("warp", (void*)&presetOutputs.warp, presetOutputs.warp_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("zoom", (void*)&presetOutputs.zoom, presetOutputs.zoom_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("rot", (void*)&presetOutputs.rot, presetOutputs.rot_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
/// @note added huge bug fix here potentially by prevening zoomexp_mesh from being freed when presets dealloc
load_builtin_param_float("zoomexp", (void*)&presetOutputs.zoomexp, presetOutputs.zoomexp_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE , 0.0, MAX_DOUBLE_SIZE, 0, "fzoomexponent");
load_builtin_param_float("cx", (void*)&presetOutputs.cx, presetOutputs.cx_mesh, P_FLAG_PER_PIXEL | P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("cy", (void*)&presetOutputs.cy, presetOutputs.cy_mesh, P_FLAG_PER_PIXEL | P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("dx", (void*)&presetOutputs.dx, presetOutputs.dx_mesh, P_FLAG_PER_PIXEL | P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("dy", (void*)&presetOutputs.dy, presetOutputs.dy_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("sx", (void*)&presetOutputs.sx, presetOutputs.sx_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("sy", (void*)&presetOutputs.sy, presetOutputs.sy_mesh, P_FLAG_PER_PIXEL |P_FLAG_NONE, 0.0, MAX_DOUBLE_SIZE, MIN_DOUBLE_SIZE, "");
load_builtin_param_float("b1n", (void*)&presetOutputs.blur1n, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("b2n", (void*)&presetOutputs.blur2n, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("b3n", (void*)&presetOutputs.blur3n, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("b1x", (void*)&presetOutputs.blur1x, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("b2x", (void*)&presetOutputs.blur2x, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("b3x", (void*)&presetOutputs.blur3x, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("b1ed", (void*)&presetOutputs.blur1ed, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("wave_r", (void*)&presetOutputs.wave.r, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("wave_g", (void*)&presetOutputs.wave.g, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("wave_b", (void*)&presetOutputs.wave.b, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("wave_x", (void*)&presetOutputs.wave.x, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("wave_y", (void*)&presetOutputs.wave.y, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("wave_mystery", (void*)&presetOutputs.wave.mystery, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "fWaveParam");
load_builtin_param_float("ob_size", (void*)&presetOutputs.border.outer_size, NULL, P_FLAG_NONE, 0.0, 0.5, 0, "");
load_builtin_param_float("ob_r", (void*)&presetOutputs.border.outer_r, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("ob_g", (void*)&presetOutputs.border.outer_g, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("ob_b", (void*)&presetOutputs.border.outer_b, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("ob_a", (void*)&presetOutputs.border.outer_a, NULL, P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("ib_size", (void*)&presetOutputs.border.inner_size, NULL,P_FLAG_NONE, 0.0, .5, 0.0, "");
load_builtin_param_float("ib_r", (void*)&presetOutputs.border.inner_r, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("ib_g", (void*)&presetOutputs.border.inner_g, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("ib_b", (void*)&presetOutputs.border.inner_b, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("ib_a", (void*)&presetOutputs.border.inner_a, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("mv_r", (void*)&presetOutputs.mv.r, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("mv_g", (void*)&presetOutputs.mv.g, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("mv_b", (void*)&presetOutputs.mv.b, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("mv_x", (void*)&presetOutputs.mv.x_num, NULL,P_FLAG_NONE, 0.0, 64.0, 0.0, "nmotionvectorsx");
load_builtin_param_float("mv_y", (void*)&presetOutputs.mv.y_num, NULL,P_FLAG_NONE, 0.0, 48.0, 0.0, "nmotionvectorsy");
load_builtin_param_float("mv_l", (void*)&presetOutputs.mv.length, NULL,P_FLAG_NONE, 0.0, 5.0, 0.0, "");
load_builtin_param_float("mv_dy", (void*)&presetOutputs.mv.x_offset, NULL, P_FLAG_NONE, 0.0, 1.0, -1.0, "");
load_builtin_param_float("mv_dx", (void*)&presetOutputs.mv.y_offset, NULL,P_FLAG_NONE, 0.0, 1.0, -1.0, "");
load_builtin_param_float("mv_a", (void*)&presetOutputs.mv.a, NULL,P_FLAG_NONE, 0.0, 1.0, 0.0, "");
load_builtin_param_float("time", (void*)&presetInputs.time, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0.0, "");
load_builtin_param_float("bass", (void*)&presetInputs.bass, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0.0, "");
load_builtin_param_float("mid", (void*)&presetInputs.mid, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, "");
load_builtin_param_float("treb", (void*)&presetInputs.treb, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, "");
load_builtin_param_float("bass_att", (void*)&presetInputs.bass_att, NULL,P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, "");
load_builtin_param_float("mid_att", (void*)&presetInputs.mid_att, NULL, P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, "");
load_builtin_param_float("treb_att", (void*)&presetInputs.treb_att, NULL, P_FLAG_READONLY, 0.0, MAX_DOUBLE_SIZE, 0, "");
load_builtin_param_int("frame", (void*)&presetInputs.frame, P_FLAG_READONLY, 0, MAX_INT_SIZE, 0, "");
load_builtin_param_float("progress", (void*)&presetInputs.progress, NULL,P_FLAG_READONLY, 0.0, 1, 0, "");
load_builtin_param_int("fps", (void*)&presetInputs.fps, P_FLAG_READONLY, 15, MAX_INT_SIZE, 0, "");
load_builtin_param_float("x", (void*)&presetInputs.x_per_pixel, presetInputs.origx, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX | P_FLAG_READONLY | P_FLAG_NONE,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, "");
load_builtin_param_float("y", (void*)&presetInputs.y_per_pixel, presetInputs.origy, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX |P_FLAG_READONLY | P_FLAG_NONE,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, "");
load_builtin_param_float("ang", (void*)&presetInputs.ang_per_pixel, presetInputs.origtheta, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX | P_FLAG_READONLY | P_FLAG_NONE,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, "");
load_builtin_param_float("rad", (void*)&presetInputs.rad_per_pixel, presetInputs.origrad, P_FLAG_PER_PIXEL |P_FLAG_ALWAYS_MATRIX | P_FLAG_READONLY | P_FLAG_NONE,
0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, "");
for (unsigned int i = 0; i < NUM_Q_VARIABLES;i++) {
std::ostringstream os;
os << "q" << i;
load_builtin_param_float(os.str().c_str(), (void*)&presetOutputs.q[i], NULL, P_FLAG_PER_PIXEL |P_FLAG_QVAR, 0, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, "");
}
/* variables added in 1.04 */
load_builtin_param_int("meshx", (void*)&presetInputs.gx, P_FLAG_READONLY, 32, 96, 8, "");
load_builtin_param_int("meshy", (void*)&presetInputs.gy, P_FLAG_READONLY, 24, 72, 6, "");
return PROJECTM_SUCCESS;
}

View File

@ -0,0 +1,86 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/** BuiltinParams.hpp :: a class to encapsulate and centralize
* all projectm builtin parameter methods and state. Used primarily
* by preset class
**/
#ifndef _BUILTIN_PARAMS_HPP
#define _BUILTIN_PARAMS_HPP
#include <string>
#include "PresetFrameIO.hpp"
#include "Param.hpp"
#include <map>
#include <cstdio>
class BuiltinParams {
public:
typedef std::map<std::string, std::string> AliasMap;
/** Default constructor leaves database in an uninitialized state. */
BuiltinParams();
/** Construct a new builtin parameter database with variables references given by
* the preset input and output structures */
BuiltinParams(PresetInputs & presetInputs, PresetOutputs & presetOutputs);
~BuiltinParams();
/** Param database initalizer / destructor functions */
int init_builtin_param_db(const PresetInputs & presetInputs, PresetOutputs & presetOutputs);
int load_all_builtin_param(const PresetInputs & presetInputs, PresetOutputs & presetOutputs);
int destroy_builtin_param_db();
int insert_param_alt_name( Param *param, const std::string& salt_name );
Param *find_builtin_param( const std::string & name );
int load_builtin_param_float( const std::string & name, void *engine_val, void *matrix,
short int flags,
float init_val, float upper_bound,
float lower_bound, const std::string & alt_name );
int load_builtin_param_int( const std::string & name, void *engine_val, short int flags,
int init_val, int upper_bound,
int lower_bound, const std::string & alt_name );
int load_builtin_param_bool( const std::string & name, void *engine_val, short int flags,
int init_val, const std::string & alt_name );
int load_builtin_param_string( const std::string & name, std::string * engine_val, short int flags);
int insert_builtin_param( Param *param );
template <class Fun>
void apply(Fun & fun) {
traverse(builtin_param_tree, fun);
}
private:
static const bool BUILTIN_PARAMS_DEBUG = false;
// Used to associate multiple string names to one parameter
AliasMap aliasMap;
// Internal datastructure to store the parameters
std::map<std::string,Param*> builtin_param_tree;
};
#endif

View File

@ -0,0 +1,19 @@
PROJECT(MilkdropPresetFactory)
cmake_minimum_required(VERSION 2.4.0)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
SET(MilkdropPresetFactory_SOURCES BuiltinFuncs.cpp Func.cpp MilkdropPreset.cpp Param.hpp PresetFrameIO.cpp CustomShape.cpp Eval.cpp MilkdropPresetFactory.cpp PerPixelEqn.cpp BuiltinParams.cpp InitCond.cpp Parser.cpp CustomWave.cpp Expr.cpp PerPointEqn.cpp Param.cpp PerFrameEqn.cpp IdlePreset.cpp)
IF(NOT MSVC)
SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
ENDIF(NOT MSVC)
INCLUDE_DIRECTORIES(${projectM_SOURCE_DIR} ${Renderer_SOURCE_DIR})
LINK_DIRECTORIES(${projectM_BINARY_DIR} ${Renderer_BINARY_DIR})
ADD_LIBRARY(MilkdropPresetFactory STATIC ${MilkdropPresetFactory_SOURCES})
SET_TARGET_PROPERTIES(MilkdropPresetFactory PROPERTIES VERSION 2.00 SOVERSION 2)
TARGET_LINK_LIBRARIES(MilkdropPresetFactory Renderer)

View File

@ -0,0 +1,38 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Value
*
* $Log$
*/
#ifndef _CVALUE_H
#define _CVALUE_H
typedef union CValue_t {
bool bool_val;
int int_val;
float float_val;
} CValue;
#endif /** _CVALUE_H */

View File

@ -0,0 +1,255 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed i 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <sstream>
#include "Common.hpp"
#include "fatal.h"
#include "CustomShape.hpp"
#include "Eval.hpp"
#include "Expr.hpp"
#include "InitCond.hpp"
#include "Param.hpp"
#include "PerFrameEqn.hpp"
#include "Preset.hpp"
#include <map>
#include "ParamUtils.hpp"
#include "InitCondUtils.hpp"
#include "wipemalloc.h"
CustomShape::CustomShape() : Shape()
{
CustomShape(0);
};
CustomShape::CustomShape ( int id ) : Shape()
{
Param * param;
this->id = id;
this->per_frame_count = 0;
/* Start: Load custom shape parameters */
param = Param::new_param_float ( "r", P_FLAG_NONE, &this->r, NULL, 1.0, 0.0, 0.5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "g", P_FLAG_NONE, &this->g, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "b", P_FLAG_NONE, &this->b, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "a", P_FLAG_NONE, &this->a, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "border_r", P_FLAG_NONE, &this->border_r, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "border_g", P_FLAG_NONE, &this->border_g, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "border_b", P_FLAG_NONE, &this->border_b, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "border_a", P_FLAG_NONE, &this->border_a, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "r2", P_FLAG_NONE, &this->r2, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "g2", P_FLAG_NONE, &this->g2, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "b2", P_FLAG_NONE, &this->b2, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "a2", P_FLAG_NONE, &this->a2, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "x", P_FLAG_NONE, &this->x, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "y", P_FLAG_NONE, &this->y, NULL, 1.0, 0.0, .5 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_bool ( "thickoutline", P_FLAG_NONE, &this->thickOutline, 1, 0, 0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_bool ( "enabled", P_FLAG_NONE, &this->enabled, 1, 0, 0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_int ( "sides", P_FLAG_NONE, &this->sides, 100, 3, 3 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_bool ( "additive", P_FLAG_NONE, &this->additive, 1, 0, 0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_bool ( "textured", P_FLAG_NONE, &this->textured, 1, 0, 0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "rad", P_FLAG_NONE, &this->radius, NULL, MAX_DOUBLE_SIZE, 0, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "ang", P_FLAG_NONE, &this->ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "tex_zoom", P_FLAG_NONE, &this->tex_zoom, NULL, MAX_DOUBLE_SIZE, .00000000001, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "tex_ang", P_FLAG_NONE, &this->tex_ang, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t1", P_FLAG_TVAR, &this->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t2", P_FLAG_TVAR, &this->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t3", P_FLAG_TVAR, &this->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t4", P_FLAG_TVAR, &this->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t5", P_FLAG_TVAR, &this->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t6", P_FLAG_TVAR, &this->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t7", P_FLAG_TVAR, &this->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
param = Param::new_param_float ( "t8", P_FLAG_TVAR, &this->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0 );
if ( !ParamUtils::insert( param, &this->param_tree ) )
{
abort();
}
for (unsigned int i = 1; i <= NUM_Q_VARIABLES;i++) {
std::ostringstream os;
os << "q" << i;
param = Param::new_param_float ( os.str().c_str(), P_FLAG_QVAR, &this->q[i], NULL, MAX_DOUBLE_SIZE,
-MAX_DOUBLE_SIZE, 0.0 );
if ( ParamUtils::insert ( param, &this->param_tree ) < 0 )
{
abort();
}
}
param = Param::new_param_string ( "imageurl", P_FLAG_NONE, &this->imageUrl);
if ( !ParamUtils::insert( param, &this->text_properties_tree ) )
{
abort();
}
}
/* Frees a custom shape form object */
CustomShape::~CustomShape()
{
traverseVector<TraverseFunctors::Delete<PerFrameEqn> > ( per_frame_eqn_tree );
traverse<TraverseFunctors::Delete<InitCond> > ( init_cond_tree );
traverse<TraverseFunctors::Delete<Param> > ( param_tree );
traverse<TraverseFunctors::Delete<InitCond> > ( per_frame_init_eqn_tree );
traverse<TraverseFunctors::Delete<Param> > ( text_properties_tree );
}
void CustomShape::loadUnspecInitConds()
{
InitCondUtils::LoadUnspecInitCond fun ( this->init_cond_tree, this->per_frame_init_eqn_tree );
traverse ( param_tree, fun );
}
void CustomShape::evalInitConds()
{
// NOTE: This is verified to be same behavior as trunk
for ( std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin();
pos != per_frame_init_eqn_tree.end();++pos )
pos->second->evaluate();
}

View File

@ -0,0 +1,90 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Encapsulation of a custom shape
*
* $Log$
*/
#ifndef _CUSTOM_SHAPE_H
#define _CUSTOM_SHAPE_H
#define CUSTOM_SHAPE_DEBUG 0
#include <map>
#include "Param.hpp"
#include "PerFrameEqn.hpp"
#include "InitCond.hpp"
#include "Renderer/Renderable.hpp"
#include <vector>
class Preset;
class CustomShape : public Shape {
public:
/* Numerical id */
int id;
int per_frame_count;
/* Parameter tree associated with this custom shape */
std::map<std::string,Param*> param_tree;
/* Engine variables */
bool enabled;
/* stupid t variables */
float t1;
float t2;
float t3;
float t4;
float t5;
float t6;
float t7;
float t8;
/* stupider q variables */
float q[NUM_Q_VARIABLES];
// Data structure to hold per frame / per frame init equations
std::map<std::string,InitCond*> init_cond_tree;
std::vector<PerFrameEqn*> per_frame_eqn_tree;
std::map<std::string,InitCond*> per_frame_init_eqn_tree;
std::map<std::string, Param*> text_properties_tree;
/// Allocate a new custom shape, including param associations, per point equations, and initial values.
/// \param id an integer id to associate with this custom wave. Future line parsing uses this as a reference key.
CustomShape( int id );
CustomShape();
~CustomShape();
void loadUnspecInitConds();
void evalInitConds();
};
#endif /** !_CUSTOM_SHAPE_H */

View File

@ -0,0 +1,539 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sstream>
#include "Common.hpp"
#include "fatal.h"
#include "CustomWave.hpp"
#include "Eval.hpp"
#include "Expr.hpp"
#include "InitCond.hpp"
#include "Param.hpp"
#include "PerFrameEqn.hpp"
#include "PerPointEqn.hpp"
#include "Preset.hpp"
#include <map>
#include "ParamUtils.hpp"
#include "InitCondUtils.hpp"
#include "wipemalloc.h"
#define MAX_SAMPLE_SIZE 4096
CustomWave::CustomWave(int _id) : Waveform(512),
id(_id),
per_frame_count(0),
r(0),
g(0),
b(0),
a(0)
{
Param * param;
/// @bug deprecate the use of wipemalloc
this->r_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->g_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->b_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->a_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->x_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->y_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->value1 = (float*) wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->value2 = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->sample_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
/* Start: Load custom wave parameters */
if ((param = Param::new_param_float("r", P_FLAG_NONE | P_FLAG_PER_POINT, &this->r, this->r_mesh, 1.0, 0.0, .5)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &param_tree) < 0)
{
/// @bug make exception
abort();
}
if ((param = Param::new_param_float("g", P_FLAG_NONE | P_FLAG_PER_POINT, &this->g, this->g_mesh, 1.0, 0.0, .5)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &param_tree) < 0)
{
;
/// @bug make exception
abort();
}
if ((param = Param::new_param_float("b", P_FLAG_NONE | P_FLAG_PER_POINT, &this->b, this->b_mesh, 1.0, 0.0, .5)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
/// @bug make exception
abort();
}
if ((param = Param::new_param_float("a", P_FLAG_NONE | P_FLAG_PER_POINT, &this->a, this->a_mesh, 1.0, 0.0, .5)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
/// @bug make exception
abort();
}
if ((param = Param::new_param_float("x", P_FLAG_NONE | P_FLAG_PER_POINT, &this->x, this->x_mesh, 1.0, 0.0, .5)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
/// @bug make exception
abort();
}
if ((param = Param::new_param_float("y", P_FLAG_NONE | P_FLAG_PER_POINT, &this->y, this->y_mesh, 1.0, 0.0, .5)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
/// @bug make exception
abort();
}
if ((param = Param::new_param_bool("enabled", P_FLAG_NONE, &this->enabled, 1, 0, 0)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
/// @bug make exception
abort();
}
if ((param = Param::new_param_int("sep", P_FLAG_NONE, &this->sep, 100, -100, 0)) == NULL)
{
;
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
/// @bug make exception
abort();
}
if ((param = Param::new_param_bool("bspectrum", P_FLAG_NONE, &this->spectrum, 1, 0, 0)) == NULL)
{
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
/// @bug make exception
abort();
}
if ((param = Param::new_param_bool("bdrawthick", P_FLAG_NONE, &this->thick, 1, 0, 0)) == NULL)
{
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
/// @bug make exception
abort();
}
if ((param = Param::new_param_bool("busedots", P_FLAG_NONE, &this->dots, 1, 0, 0)) == NULL)
{
/// @bug make exception
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_bool("badditive", P_FLAG_NONE, &this->additive, 1, 0, 0)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_int("samples", P_FLAG_NONE, &this->samples, 2048, 1, 512)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_float("sample", P_FLAG_READONLY | P_FLAG_NONE | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT,
&this->sample, this->sample_mesh, 1.0, 0.0, 0.0)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
abort();
}
if ((param = Param::new_param_float("value1", P_FLAG_READONLY | P_FLAG_NONE | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT, &this->v1, this->value1, 1.0, -1.0, 0.0)) == NULL)
{
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
abort();
}
if ((param = Param::new_param_float("value2", P_FLAG_READONLY | P_FLAG_NONE | P_FLAG_ALWAYS_MATRIX | P_FLAG_PER_POINT, &this->v2, this->value2, 1.0, -1.0, 0.0)) == NULL)
{
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_float("smoothing", P_FLAG_NONE, &this->smoothing, NULL, 1.0, 0.0, 0.0)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_float("scaling", P_FLAG_NONE, &this->scaling, NULL, MAX_DOUBLE_SIZE, 0.0, 1.0)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_float("t1", P_FLAG_PER_POINT | P_FLAG_TVAR, &this->t1, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_float("t2", P_FLAG_PER_POINT |P_FLAG_TVAR, &this->t2, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
abort();
}
if ((param = Param::new_param_float("t3", P_FLAG_PER_POINT |P_FLAG_TVAR, &this->t3, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
abort();
}
if ((param = Param::new_param_float("t4", P_FLAG_PER_POINT |P_FLAG_TVAR, &this->t4, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
abort();
}
if ((param = Param::new_param_float("t5", P_FLAG_TVAR, &this->t5, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
abort();
}
if ((param = Param::new_param_float("t6", P_FLAG_TVAR | P_FLAG_PER_POINT, &this->t6, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
abort();
}
if ((param = Param::new_param_float("t7", P_FLAG_TVAR | P_FLAG_PER_POINT, &this->t7, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
if ((param = Param::new_param_float("t8", P_FLAG_TVAR | P_FLAG_PER_POINT, &this->t8, NULL, MAX_DOUBLE_SIZE, -MAX_DOUBLE_SIZE, 0.0)) == NULL)
{
;
abort();
}
if (ParamUtils::insert(param, &this->param_tree) < 0)
{
;
abort();
}
for (unsigned int i = 1; i <= NUM_Q_VARIABLES;i++) {
std::ostringstream os;
os << "q" << i;
param = Param::new_param_float ( os.str().c_str(), P_FLAG_QVAR, &this->q[i], NULL, MAX_DOUBLE_SIZE,
-MAX_DOUBLE_SIZE, 0.0 );
if ( ParamUtils::insert ( param, &this->param_tree ) < 0 )
{
abort();
}
}
/* End of parameter loading. Note that the read only parameters associated
with custom waves (ie, sample) are variables stored in PresetFrameIO.hpp,
and not specific to the custom wave datastructure. */
}
CustomWave::~CustomWave()
{
for (std::vector<PerPointEqn*>::iterator pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end(); ++pos)
delete(*pos);
for (std::vector<PerFrameEqn*>::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos)
delete(*pos);
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
delete(pos->second);
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
delete(pos->second);
for (std::map<std::string, Param*>::iterator pos = param_tree.begin(); pos != param_tree.end(); ++pos)
delete(pos->second);
free(r_mesh);
free(g_mesh);
free(b_mesh);
free(a_mesh);
free(x_mesh);
free(y_mesh);
free(value1);
free(value2);
free(sample_mesh);
}
// Comments: index is not passed, so we assume monotonic increment by 1 is ok here
int CustomWave::add_per_point_eqn(char * name, GenExpr * gen_expr)
{
PerPointEqn * per_point_eqn;
int index;
Param * param = NULL;
/* Argument checks */
if (gen_expr == NULL)
return PROJECTM_FAILURE;
if (name == NULL)
return PROJECTM_FAILURE;
if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: per pixel equation (name = \"%s\")\n", name);
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
if ((param = ParamUtils::find<ParamUtils::AUTO_CREATE>(name,&param_tree)) == NULL)
{
if (CUSTOM_WAVE_DEBUG) printf("add_per_point_eqn: failed to allocate a new parameter!\n");
return PROJECTM_FAILURE;
}
/* Get largest index in the tree */
index = per_point_eqn_tree.size();
/* Create the per point equation given the index, parameter, and general expression */
if ((per_point_eqn = new PerPointEqn(index, param, gen_expr, samples)) == NULL)
return PROJECTM_FAILURE;
if (CUSTOM_WAVE_DEBUG)
printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name.c_str());
/* Insert the per pixel equation into the preset per pixel database */
per_point_eqn_tree.push_back(per_point_eqn);
/* Done */
return PROJECTM_SUCCESS;
}
void CustomWave::evalInitConds()
{
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
{
assert(pos->second);
pos->second->evaluate();
}
}
ColoredPoint CustomWave::PerPoint(ColoredPoint p, const WaveformContext context)
{
r_mesh[context.sample_int] = r;
g_mesh[context.sample_int] = g;
b_mesh[context.sample_int] = b;
a_mesh[context.sample_int] = a;
x_mesh[context.sample_int] = x;
y_mesh[context.sample_int] = y;
sample = context.sample;
sample_mesh[context.sample_int] = context.sample;
v1 = context.left;
v2 = context.right;
for (std::vector<PerPointEqn*>::iterator pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end();++pos)
(*pos)->evaluate(context.sample_int);
p.a = a_mesh[context.sample_int];
p.r = r_mesh[context.sample_int];
p.g = g_mesh[context.sample_int];
p.b = b_mesh[context.sample_int];
p.x = x_mesh[context.sample_int];
p.y = y_mesh[context.sample_int];
return p;
}
void CustomWave::loadUnspecInitConds()
{
InitCondUtils::LoadUnspecInitCond fun(this->init_cond_tree, this->per_frame_init_eqn_tree);
traverse(param_tree, fun);
}

View File

@ -0,0 +1,128 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Encapsulation of a custom wave
*
* $Log$
*/
#ifndef _CUSTOM_WAVE_H
#define _CUSTOM_WAVE_H
#define CUSTOM_WAVE_DEBUG 0
class CustomWave;
class GenExpr;
class PerPointEqn;
class Preset;
#include <vector>
#include "Common.hpp"
#include "Param.hpp"
#include "PerFrameEqn.hpp"
#include "Renderer/Waveform.hpp"
#include <map>
class CustomWave : public Waveform
{
public:
/** Empty constructor leaves wave in undefined state **/
//CustomWave() {}
/** Initializes a custom wave id given the integer id */
CustomWave(int id);
/** Destructor is necessary so we can free the per point matrices **/
~CustomWave();
ColoredPoint PerPoint(ColoredPoint p, const WaveformContext context);
/* Numerical id */
int id;
int per_frame_count;
/* Parameter tree associated with this custom wave */
std::map<std::string,Param*> param_tree;
/* Engine variables */
float x; /* x position for per point equations */
float y; /* y position for per point equations */
float r; /* red color value */
float g; /* green color value */
float b; /* blue color value */
float a; /* alpha color value */
float * x_mesh;
float * y_mesh;
float * r_mesh;
float * b_mesh;
float * g_mesh;
float * a_mesh;
float * value1;
float * value2;
float * sample_mesh;
bool enabled; /* if true then wave is visible, hidden otherwise */
float sample;
/* stupid t variables */
float t1;
float t2;
float t3;
float t4;
float t5;
float t6;
float t7;
float t8;
/* stupider q variables */
float q[NUM_Q_VARIABLES];
float v1,v2;
/* Data structures to hold per frame and per point equations */
std::map<std::string,InitCond*> init_cond_tree;
std::vector<PerFrameEqn*> per_frame_eqn_tree;
std::vector<PerPointEqn*> per_point_eqn_tree;
std::map<std::string,InitCond*> per_frame_init_eqn_tree;
/* Denotes the index of the last character for each string buffer */
int per_point_eqn_string_index;
int per_frame_eqn_string_index;
int per_frame_init_eqn_string_index;
int add_per_point_eqn(char * name, GenExpr * gen_expr);
void evalCustomWaveInitConditions(Preset *preset);
void loadUnspecInitConds();
void evalInitConds();
};
#endif /** !_CUSTOM_WAVE_H */

View File

@ -0,0 +1,91 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/* Evaluation Code */
#include <cstdio>
#include <cstdlib>
#include "Common.hpp"
#include "fatal.h"
#include "Eval.hpp"
#include "Expr.hpp"
#include "Param.hpp"
#include "Func.hpp"
#include "wipemalloc.h"
#include "BuiltinFuncs.hpp"
InfixOp *Eval::infix_add = NULL;
InfixOp *Eval::infix_minus = NULL;
InfixOp *Eval::infix_div = NULL;
InfixOp *Eval::infix_mult = NULL;
InfixOp *Eval::infix_or = NULL;
InfixOp *Eval::infix_and = NULL;
InfixOp *Eval::infix_mod = NULL;
InfixOp *Eval::infix_negative = NULL;
InfixOp *Eval::infix_positive = NULL;
/* Initializes all infix operators */
int Eval::init_infix_ops() {
Eval::infix_add = new InfixOp(INFIX_ADD, 4);
Eval::infix_minus = new InfixOp(INFIX_MINUS, 3);
Eval::infix_div = new InfixOp(INFIX_DIV, 2);
Eval::infix_or = new InfixOp(INFIX_OR, 5);
Eval::infix_and = new InfixOp(INFIX_AND,4);
Eval::infix_mod = new InfixOp(INFIX_MOD, 1);
Eval::infix_mult = new InfixOp(INFIX_MULT, 2);
/* Prefix operators */
Eval::infix_positive = new InfixOp(INFIX_ADD, 0);
Eval::infix_negative = new InfixOp(INFIX_MINUS, 0);
return PROJECTM_SUCCESS;
}
/* Destroys the infix operator list. This should
be done on program exit */
int Eval::destroy_infix_ops()
{
delete(Eval::infix_add);
delete(Eval::infix_minus);
delete(Eval::infix_div);
delete(Eval::infix_or);
delete(Eval::infix_and);
delete(Eval::infix_mod);
delete(Eval::infix_mult);
delete(Eval::infix_positive);
delete(Eval::infix_negative);
Eval::infix_add = NULL;
Eval::infix_minus = NULL;
Eval::infix_div = NULL;
Eval::infix_or = NULL;
Eval::infix_and = NULL;
Eval::infix_mod = NULL;
Eval::infix_mult = NULL;
Eval::infix_positive = NULL;
Eval::infix_negative = NULL;
return PROJECTM_SUCCESS;
}

View File

@ -0,0 +1,94 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Expression evaluators
*
* $Log$
*/
/* Eval.hpp: evaluation functions of expressions */
#ifndef __EVAL_H
#define __EVAL_H
#include "fatal.h"
//#include "projectM.hpp"
#include "Func.hpp"
#include "Param.hpp"
#define EVAL_DEBUG 0
//#define EVAL_DEBUG_DOUBLE 2
#define VAL_T 1
#define PREFUN_T 3
#define TREE_T 4
#define NONE_T 0
#define CONSTANT_TERM_T 0
#define PARAM_TERM_T 1
#define INFIX_ADD 0
#define INFIX_MINUS 1
#define INFIX_MOD 2
#define INFIX_DIV 3
#define INFIX_MULT 4
#define INFIX_OR 5
#define INFIX_AND 6
class DLLEXPORT InfixOp;
class Eval {
public:
static InfixOp *infix_add,
*infix_minus,
*infix_div,
*infix_mult,
*infix_or,
*infix_and,
*infix_mod,
*infix_negative,
*infix_positive;
float eval_gen_expr(GenExpr * gen_expr);
inline GenExpr * opt_gen_expr(GenExpr * gen_expr, int ** param_list);
GenExpr * const_to_expr(float val);
GenExpr * param_to_expr(Param * param);
GenExpr * prefun_to_expr(float (*func_ptr)(), GenExpr ** expr_list, int num_args);
static TreeExpr * new_tree_expr(InfixOp * infix_op, GenExpr * gen_expr, TreeExpr * left, TreeExpr * right);
static GenExpr * new_gen_expr(int type, void * item);
static ValExpr * new_val_expr(int type, Term *term);
static InfixOp * new_infix_op(int type, int precedence);
static int init_infix_ops();
static int destroy_infix_ops();
void reset_engine_vars();
GenExpr * clone_gen_expr(GenExpr * gen_expr);
TreeExpr * clone_tree_expr(TreeExpr * tree_expr);
ValExpr * clone_val_expr(ValExpr * val_expr);
PrefunExpr * clone_prefun_expr(PrefunExpr * prefun_expr);
};
#endif /** !_EVAL_H */

View File

@ -0,0 +1,375 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include "wipemalloc.h"
#include "Expr.hpp"
#include <cassert>
#include <iostream>
#include "Eval.hpp"
float GenExpr::eval_gen_expr ( int mesh_i, int mesh_j )
{
float l;
assert ( item );
switch ( this->type )
{
case VAL_T:
return ( ( ValExpr* ) item )->eval_val_expr ( mesh_i, mesh_j );
case PREFUN_T:
l = ( ( PrefunExpr * ) item )->eval_prefun_expr ( mesh_i, mesh_j );
//if (EVAL_DEBUG) DWRITE( "eval_gen_expr: prefix function return value: %f\n", l);
return l;
case TREE_T:
return ( ( TreeExpr* ) ( item ) )->eval_tree_expr ( mesh_i, mesh_j );
default:
return EVAL_ERROR;
}
}
/* Evaluates functions in prefix form */
float PrefunExpr::eval_prefun_expr ( int mesh_i, int mesh_j )
{
assert ( func_ptr );
float * arg_list = new float[this->num_args];
assert(arg_list);
//printf("numargs %d", num_args);
/* Evaluate each argument before calling the function itself */
for ( int i = 0; i < num_args; i++ )
{
arg_list[i] = expr_list[i]->eval_gen_expr ( mesh_i, mesh_j );
//printf("numargs %x", arg_list[i]);
}
/* Now we call the function, passing a list of
floats as its argument */
const float value = ( func_ptr ) ( arg_list );
delete[](arg_list);
return value;
}
/* Evaluates a value expression */
float ValExpr::eval_val_expr ( int mesh_i, int mesh_j )
{
/* Value is a constant, return the float value */
if ( type == CONSTANT_TERM_T )
{
return ( term.constant );
}
/* Value is variable, dereference it */
if ( type == PARAM_TERM_T )
{
switch ( term.param->type )
{
case P_TYPE_BOOL:
return ( float ) ( * ( ( bool* ) ( term.param->engine_val ) ) );
case P_TYPE_INT:
return ( float ) ( * ( ( int* ) ( term.param->engine_val ) ) );
case P_TYPE_DOUBLE:
if ( term.param->matrix_flag | ( term.param->flags & P_FLAG_ALWAYS_MATRIX ) )
{
/* Sanity check the matrix is there... */
assert ( term.param->matrix != NULL );
/// @slow boolean check could be expensive in this critical (and common) step of evaluation
if ( mesh_i >= 0 )
{
if ( mesh_j >= 0 )
{
return ( ( ( float** ) term.param->matrix ) [mesh_i][mesh_j] );
}
else
{
return ( ( ( float* ) term.param->matrix ) [mesh_i] );
}
}
//assert(mesh_i >=0);
}
//std::cout << term.param->name << ": " << (*((float*)term.param->engine_val)) << std::endl;
return * ( ( float* ) ( term.param->engine_val ) );
default:
return EVAL_ERROR;
}
}
/* Unknown type, return failure */
return PROJECTM_FAILURE;
}
/* Evaluates an expression tree */
float TreeExpr::eval_tree_expr ( int mesh_i, int mesh_j )
{
float left_arg, right_arg;
/* A leaf node, evaluate the general expression. If the expression is null as well, return zero */
if ( infix_op == NULL )
{
if ( gen_expr == NULL )
return 0;
else
return gen_expr->eval_gen_expr ( mesh_i, mesh_j );
}
/* Otherwise, this node is an infix operator. Evaluate
accordingly */
assert(left);
left_arg = left->eval_tree_expr ( mesh_i, mesh_j );
assert(right);
right_arg = right->eval_tree_expr ( mesh_i, mesh_j );
switch ( infix_op->type )
{
case INFIX_ADD:
return ( left_arg + right_arg );
case INFIX_MINUS:
return ( left_arg - right_arg );
case INFIX_MULT:
return ( left_arg * right_arg );
case INFIX_MOD:
if ( ( int ) right_arg == 0 )
{
return PROJECTM_DIV_BY_ZERO;
}
return ( ( int ) left_arg % ( int ) right_arg );
case INFIX_OR:
return ( ( int ) left_arg | ( int ) right_arg );
case INFIX_AND:
return ( ( int ) left_arg & ( int ) right_arg );
case INFIX_DIV:
if ( right_arg == 0 )
{
return MAX_DOUBLE_SIZE;
}
return ( left_arg / right_arg );
default:
return EVAL_ERROR;
}
return EVAL_ERROR;
}
/* Converts a float value to a general expression */
GenExpr * GenExpr::const_to_expr ( float val )
{
GenExpr * gen_expr;
ValExpr * val_expr;
Term term;
term.constant = val;
if ( ( val_expr = new ValExpr ( CONSTANT_TERM_T, &term ) ) == NULL )
return NULL;
gen_expr = new GenExpr ( VAL_T, ( void* ) val_expr );
if ( gen_expr == NULL )
{
delete val_expr;
}
return gen_expr;
}
/* Converts a regular parameter to an expression */
GenExpr * GenExpr::param_to_expr ( Param * param )
{
GenExpr * gen_expr = NULL;
ValExpr * val_expr = NULL;
Term term;
if ( param == NULL )
return NULL;
/* This code is still a work in progress. We need
to figure out if the initial condition is used for
each per frame equation or not. I am guessing that
it isn't, and it is thusly implemented this way */
/* Current guess of true behavior (08/01/03) note from carm
First try to use the per_pixel_expr (with cloning)
If it is null however, use the engine variable instead. */
/* 08/20/03 : Presets are now objects, as well as per pixel equations. This ends up
making the parser handle the case where parameters are essentially per pixel equation
substitutions */
term.param = param;
if ( ( val_expr = new ValExpr ( PARAM_TERM_T, &term ) ) == NULL )
return NULL;
if ( ( gen_expr = new GenExpr ( VAL_T, ( void* ) val_expr ) ) == NULL )
{
delete val_expr;
return NULL;
}
return gen_expr;
}
/* Converts a prefix function to an expression */
GenExpr * GenExpr::prefun_to_expr ( float ( *func_ptr ) ( void * ), GenExpr ** expr_list, int num_args )
{
GenExpr * gen_expr;
PrefunExpr * prefun_expr;
prefun_expr = new PrefunExpr();
if ( prefun_expr == NULL )
return NULL;
prefun_expr->num_args = num_args;
prefun_expr->func_ptr = ( float ( * ) ( void* ) ) func_ptr;
prefun_expr->expr_list = expr_list;
gen_expr = new GenExpr ( PREFUN_T, ( void* ) prefun_expr );
if ( gen_expr == NULL )
delete prefun_expr;
return gen_expr;
}
/* Creates a new tree expression */
TreeExpr::TreeExpr ( InfixOp * _infix_op, GenExpr * _gen_expr, TreeExpr * _left, TreeExpr * _right ) :
infix_op ( _infix_op ), gen_expr ( _gen_expr ),
left ( _left ), right ( _right ) {}
/* Creates a new value expression */
ValExpr::ValExpr ( int _type, Term * _term ) :type ( _type )
{
//val_expr->type = _type;
term.constant = _term->constant;
term.param = _term->param;
//return val_expr;
}
/* Creates a new general expression */
GenExpr::GenExpr ( int _type, void * _item ) :type ( _type ), item ( _item ) {}
/* Frees a general expression */
GenExpr::~GenExpr()
{
switch ( type )
{
case VAL_T:
delete ( ( ValExpr* ) item );
break;
case PREFUN_T:
delete ( ( PrefunExpr* ) item );
break;
case TREE_T:
delete ( ( TreeExpr* ) item );
break;
}
}
/* Frees a function in prefix notation */
PrefunExpr::~PrefunExpr()
{
int i;
/* Free every element in expression list */
for ( i = 0 ; i < num_args; i++ )
{
delete expr_list[i];
}
free ( expr_list );
}
/* Frees values of type VARIABLE and CONSTANT */
ValExpr::~ValExpr()
{}
/* Frees a tree expression */
TreeExpr::~TreeExpr()
{
/* free left tree */
if ( left != NULL )
{
delete left;
}
/* free general expression object */
if ( gen_expr != NULL )
{
delete gen_expr;
}
/* Note that infix operators are always
stored in memory unless the program
exits, so we don't remove them here */
/* free right tree */
if ( right != NULL )
{
delete right;
}
}
/* Initializes an infix operator */
InfixOp::InfixOp ( int type, int precedence )
{
this->type = type;
this->precedence = precedence;
}
PrefunExpr::PrefunExpr() {}

View File

@ -0,0 +1,122 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Expression
*
* $Log$
*/
#ifndef _EXPR_H
#define _EXPR_H
#include "dlldefs.h"
#include "CValue.hpp"
class Param;
#define CONST_STACK_ELEMENT 0
#define EXPR_STACK_ELEMENT 1
#define EVAL_ERROR -1
/* Infix Operator Function */
class InfixOp
{
public:
int type;
int precedence;
InfixOp( int type, int precedence );
};
/** Term */
class Term
{
public:
float constant; /* static variable */
Param *param; /* pointer to a changing variable */
Term() { this->constant = 0; this->param = 0; }
};
/* General Expression Type */
class GenExpr
{
public:
int type;
void * item;
~GenExpr();
GenExpr( int type, void *item );
float eval_gen_expr(int mesh_i, int mesh_j);
static GenExpr *const_to_expr( float val );
static GenExpr *param_to_expr( Param *param );
static GenExpr *prefun_to_expr( float (*func_ptr)(void *), GenExpr **expr_list, int num_args );
};
/* Value expression, contains a term union */
class ValExpr
{
public:
int type;
Term term;
~ValExpr();
ValExpr( int type, Term *term );
float eval_val_expr(int mesh_i, int mesh_j);
};
/* A binary expression tree ordered by operator precedence */
class TreeExpr
{
public:
InfixOp * infix_op; /* null if leaf */
GenExpr * gen_expr;
TreeExpr *left, *right;
~TreeExpr();
TreeExpr( InfixOp *infix_op, GenExpr *gen_expr,
TreeExpr *left, TreeExpr *right );
float eval_tree_expr(int mesh_i, int mesh_j);
};
/* A function expression in prefix form */
class PrefunExpr
{
public:
float (*func_ptr)(void*);
int num_args;
GenExpr **expr_list;
PrefunExpr();
~PrefunExpr();
/* Evaluates functions in prefix form */
float eval_prefun_expr(int mesh_i, int mesh_j);
};
#endif /** _EXPR_H */

View File

@ -0,0 +1,37 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/* Function management */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "Common.hpp"
#include "fatal.h"
#include "Func.hpp"
#include <map>
Func::Func (const std::string & _name, float (*_func_ptr)(float*), int _num_args):
name(_name), func_ptr(_func_ptr), num_args(_num_args) {}
/* Frees a function type, real complicated... */
Func::~Func() {}

View File

@ -0,0 +1,63 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Function
*
* $Log$
*/
#ifndef _FUNC_H
#define _FUNC_H
#include "Common.hpp"
#include <string>
/* Function Type */
class DLLEXPORT Func {
public:
/// Create a new function wrapper object
/// \param name a name to uniquely identify the function.
/// \param func_ptr a pointer to a function of floating point arguments
/// \param num_args the number of floating point arguments this function requires
Func(const std::string & name, float (*func_ptr)(float*), int num_args );
/* Public Prototypes */
~Func();
inline const std::string & getName() const {
return name;
}
inline int getNumArgs() const {
return num_args;
}
float (*func_ptr)(float*);
private:
std::string name;
int num_args;
};
#endif /** !_FUNC_H */

View File

@ -0,0 +1,209 @@
#include "IdlePreset.hpp"
#include <sstream>
#include <string>
#include "MilkdropPreset.hpp"
const std::string IdlePresets::IDLE_PRESET_NAME
("Geiss & Sperl - Feedback (projectM idle HDR mix).milk");
std::string IdlePresets::presetText() {
std::ostringstream out;
out << "[preset00]\n" <<
"fRating=2.000000\n" <<
"fGammaAdj=1.700000\n" <<
"fDecay=0.940000\n" <<
"fVideoEchoZoom=1.000000\n" <<
"fVideoEchoAlpha=0.000000\n" <<
"nVideoEchoOrientation=0\n" <<
"nWaveMode=0\n" <<
"bAdditiveWaves=1\n" <<
"bWaveDots=0\n" <<
"bWaveThick=0\n" <<
"bModWaveAlphaByVolume=0\n" <<
"bMaximizeWaveColor=0\n" <<
"bTexWrap=1\n" <<
"bDarkenCenter=0\n" <<
"bRedBlueStereo=0\n" <<
"bBrighten=0\n" <<
"bDarken=0\n" <<
"bSolarize=0\n" <<
"bInvert=0\n" <<
"fWaveAlpha=0.001000\n" <<
"fWaveScale=0.010000\n" <<
"fWaveSmoothing=0.630000\n" <<
"fWaveParam=-1.000000\n" <<
"fModWaveAlphaStart=0.710000\n" <<
"fModWaveAlphaEnd=1.300000\n" <<
"fWarpAnimSpeed=1.000000\n" <<
"fWarpScale=1.331000\n" <<
"fZoomExponent=1.000000\n" <<
"fShader=0.000000\n" <<
"zoom=13.290894\n" <<
"rot=-0.020000\n" <<
"cx=0.500000\n" <<
"cy=0.500000\n" <<
"dx=-0.280000\n" <<
"dy=-0.320000\n" <<
"warp=0.010000\n" <<
"sx=1.000000\n" <<
"sy=1.000000\n" <<
"wave_r=0.650000\n" <<
"wave_g=0.650000\n" <<
"wave_b=0.650000\n" <<
"wave_x=0.500000\n" <<
"wave_y=0.500000\n" <<
"ob_size=0.000000\n" <<
"ob_r=0.010000\n" <<
"ob_g=0.000000\n" <<
"ob_b=0.000000\n" <<
"ob_a=1.000000\n" <<
"ib_size=0.000000\n" <<
"ib_r=0.950000\n" <<
"ib_g=0.850000\n" <<
"ib_b=0.650000\n" <<
"ib_a=1.000000\n" <<
"nMotionVectorsX=64.000000\n" <<
"nMotionVectorsY=0.000000\n" <<
"mv_dx=0.000000\n" <<
"mv_dy=0.000000\n" <<
"mv_l=0.900000\n" <<
"mv_r=1.000000\n" <<
"mv_g=1.000000\n" <<
"mv_b=1.000000\n" <<
"mv_a=0.000000\n" <<
"shapecode_3_enabled=1\n" <<
"shapecode_3_sides=20\n" <<
"shapecode_3_additive=0\n" <<
"shapecode_3_thickOutline=0\n" <<
"shapecode_3_textured=1\n" <<
"shapecode_3_ImageURL=M.tga\n" <<
"shapecode_3_x=0.68\n" <<
"shapecode_3_y=0.5\n" <<
"shapecode_3_rad=0.41222\n" <<
"shapecode_3_ang=0\n" <<
"shapecode_3_tex_ang=0\n" <<
"shapecode_3_tex_zoom=0.71\n" <<
"shapecode_3_r=1\n" <<
"shapecode_3_g=1\n" <<
"shapecode_3_b=1\n" <<
"shapecode_3_a=1\n" <<
"shapecode_3_r2=1\n" <<
"shapecode_3_g2=1\n" <<
"shapecode_3_b2=1\n" <<
"shapecode_3_a2=1\n" <<
"shapecode_3_border_r=0\n" <<
"shapecode_3_border_g=0\n" <<
"shapecode_3_border_b=0\n" <<
"shapecode_3_border_a=0\n" <<
"shape_3_per_frame1=x = x + q1;\n" <<
"shape_3_per_frame2=y = y + q2;\n" <<
"shape_3_per_frame3=r =0.5 + 0.5*sin(q8*0.613 + 1);\n" <<
"shape_3_per_frame4=g = 0.5 + 0.5*sin(q8*0.763 + 2);\n" <<
"shape_3_per_frame5=b = 0.5 + 0.5*sin(q8*0.771 + 5);\n" <<
"shape_3_per_frame6=r2 = 0.5 + 0.5*sin(q8*0.635 + 4);\n" <<
"shape_3_per_frame7=g2 = 0.5 + 0.5*sin(q8*0.616+ 1);\n" <<
"shape_3_per_frame8=b2 = 0.5 + 0.5*sin(q8*0.538 + 3);\n" <<
"shapecode_4_enabled=1\n" <<
"shapecode_4_sides=4\n" <<
"shapecode_4_additive=0\n" <<
"shapecode_4_thickOutline=0\n" <<
"shapecode_4_textured=1\n" <<
"shapecode_4_ImageURL=headphones.tga\n" <<
"shapecode_4_x=0.68\n" <<
"shapecode_4_y=0.58\n" <<
"shapecode_4_rad=0.6\n" <<
"shapecode_4_ang=0\n" <<
"shapecode_4_tex_ang=0\n" <<
"shapecode_4_tex_zoom=0.71\n" <<
"shapecode_4_r=1\n" <<
"shapecode_4_g=1\n" <<
"shapecode_4_b=1\n" <<
"shapecode_4_a=1\n" <<
"shapecode_4_r2=1\n" <<
"shapecode_4_g2=1\n" <<
"shapecode_4_b2=1\n" <<
"shapecode_4_a2=1\n" <<
"shapecode_4_border_r=0\n" <<
"shapecode_4_border_g=0\n" <<
"shapecode_4_border_b=0\n" <<
"shapecode_4_border_a=0\n" <<
"shape_4_per_frame1=x = x + q1;\n" <<
"shape_4_per_frame2=y = y + q2;\n" <<
"shape_4_per_frame3=rad = rad + bass * 0.1;\n" <<
"shape_4_per_frame4=a = q3;\n" <<
"shape_4_per_frame5=a2 = q3;\n" <<
"shapecode_6_enabled=1\n" <<
"shapecode_6_sides=4\n" <<
"shapecode_6_additive=0\n" <<
"shapecode_6_thickOutline=0\n" <<
"shapecode_6_textured=1\n" <<
"shapecode_6_ImageURL=project.tga\n" <<
"shapecode_6_x=0.38\n" <<
"shapecode_6_y=0.435\n" <<
"shapecode_6_rad=0.8\n" <<
"shapecode_6_ang=0\n" <<
"shapecode_6_tex_ang=0\n" <<
"shapecode_6_tex_zoom=0.71\n" <<
"shapecode_6_r=1\n" <<
"shapecode_6_g=1\n" <<
"shapecode_6_b=1\n" <<
"shapecode_6_a=1\n" <<
"shapecode_6_r2=1\n" <<
"shapecode_6_g2=1\n" <<
"shapecode_6_b2=1\n" <<
"shapecode_6_a2=1\n" <<
"shapecode_6_border_r=0\n" <<
"shapecode_6_border_g=0\n" <<
"shapecode_6_border_b=0\n" <<
"shapecode_6_border_a=0\n" <<
"shape_6_per_frame1=x = x + q1;\n" <<
"shape_6_per_frame2=y = y + q2;\n" <<
"shape_6_per_frame3=a = q3;\n" <<
"shape_6_per_frame4=a2 = q3;\n" <<
"per_frame_1=ob_r = 0.5 + 0.4*sin(time*1.324);\n" <<
"per_frame_2=ob_g = 0.5 + 0.4*cos(time*1.371);\n" <<
"per_frame_3=ob_b = 0.5+0.4*sin(2.332*time);\n" <<
"per_frame_4=ib_r = 0.5 + 0.25*sin(time*1.424);\n" <<
"per_frame_5=ib_g = 0.25 + 0.25*cos(time*1.871);\n" <<
"per_frame_6=ib_b = 1-ob_b;\n" <<
"per_frame_7=volume = 0.15*(bass+bass_att+treb+treb_att+mid+mid_att);\n" <<
"per_frame_8=xamptarg = if(equal(frame%15,0),min(0.5*volume*bass_att,0.5),xamptarg);\n" <<
"per_frame_9=xamp = xamp + 0.5*(xamptarg-xamp);\n" <<
"per_frame_10=xdir = if(above(abs(xpos),xamp),-sign(xpos),if(below(abs(xspeed),0.1),2*above(xpos,0)-1,xdir));\n" <<
"per_frame_11=xaccel = xdir*xamp - xpos - xspeed*0.055*below(abs(xpos),xamp);\n" <<
"per_frame_12=xspeed = xspeed + xdir*xamp - xpos - xspeed*0.055*below(abs(xpos),xamp);\n" <<
"per_frame_13=xpos = xpos + 0.001*xspeed;\n" <<
"per_frame_14=dx = xpos*0.05;\n" <<
"per_frame_15=yamptarg = if(equal(frame%15,0),min(0.3*volume*treb_att,0.5),yamptarg);\n" <<
"per_frame_16=yamp = yamp + 0.5*(yamptarg-yamp);\n" <<
"per_frame_17=ydir = if(above(abs(ypos),yamp),-sign(ypos),if(below(abs(yspeed),0.1),2*above(ypos,0)-1,ydir));\n" <<
"per_frame_18=yaccel = ydir*yamp - ypos - yspeed*0.055*below(abs(ypos),yamp);\n" <<
"per_frame_19=yspeed = yspeed + ydir*yamp - ypos - yspeed*0.055*below(abs(ypos),yamp);\n" <<
"per_frame_20=ypos = ypos + 0.001*yspeed;\n" <<
"per_frame_21=dy = ypos*0.05;\n" <<
"per_frame_22=wave_a = 0;\n" <<
"per_frame_23=q8 = oldq8 + 0.0003*(pow(1+1.2*bass+0.4*bass_att+0.1*treb+0.1*treb_att+0.1*mid+0.1*mid_att,6)/fps);\n" <<
"per_frame_24=oldq8 = q8;\n" <<
"per_frame_25=q7 = 0.003*(pow(1+1.2*bass+0.4*bass_att+0.1*treb+0.1*treb_att+0.1*mid+0.1*mid_att,6)/fps);\n" <<
"per_frame_26=rot = 0.4 + 1.5*sin(time*0.273) + 0.4*sin(time*0.379+3);\n" <<
"per_frame_27=q1 = 0.05*sin(time*1.14);\n" <<
"per_frame_28=q2 = 0.03*sin(time*0.93+2);\n" <<
"per_frame_29=q3 = if(above(frame,60),1, frame/60.0);\n" <<
"per_frame_30=oldq8 = if(above(oldq8,1000),0,oldq8);\n" <<
"per_pixel_1=zoom =( log(sqrt(2)-rad) -0.24)*1;\n";
return out.str();
}
std::auto_ptr<Preset> IdlePresets::allocate(const std::string & name, PresetOutputs & presetOutputs)
{
if (name == IDLE_PRESET_NAME) {
std::istringstream in(presetText());
return std::auto_ptr<Preset>(new MilkdropPreset(in, IDLE_PRESET_NAME, presetOutputs));
}
else
return std::auto_ptr<Preset>(0);
}

View File

@ -0,0 +1,20 @@
#ifndef IDLE_PRESET_HPP
#define IDLE_PRESET_HPP
#include <memory>
#include <string>
class PresetOutputs;
class Preset;
/// A preset that does not depend on the file system to be loaded. This allows projectM to render
/// something (ie. self indulgent project advertising) even when no valid preset directory is found.
class IdlePresets {
public:
/// Allocate a new idle preset instance
/// \returns a newly allocated auto pointer of an idle preset instance
static std::auto_ptr<Preset> allocate(const std::string & path, PresetOutputs & outputs);
private:
static std::string presetText();
static const std::string IDLE_PRESET_NAME;
};
#endif

View File

@ -0,0 +1,147 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/* Library functions to manipulate initial condition values */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Common.hpp"
#include "fatal.h"
#include "Expr.hpp"
#include "InitCond.hpp"
#include "Param.hpp"
#include <map>
#include "wipemalloc.h"
#include <cassert>
#include <iostream>
char InitCond::init_cond_string_buffer[STRING_BUFFER_SIZE];
int InitCond::init_cond_string_buffer_index = 0;
/* Creates a new initial condition */
InitCond::InitCond( Param * _param, CValue _init_val ):param(_param), init_val(_init_val) {
// std::cerr << "InitCond::InitCond: " << this->param->name << std::endl;
assert(param);
assert(param->engine_val);
}
/* Frees initial condition structure */
InitCond::~InitCond() {}
void InitCond::evaluate()
{
evaluate(false);
}
/* Evaluate an initial conditon */
void InitCond::evaluate(bool evalUser) {
assert(this);
assert(param);
if (param->flags & P_FLAG_USERDEF && !evalUser)
return;
/* Set matrix flag to zero. This ensures
its constant value will be used rather than a matrix value
*/
param->matrix_flag = false;
/* Parameter is of boolean type, either true/false */
if (param->type == P_TYPE_BOOL) {
// printf( "init_cond: %s = %d (TYPE BOOL)\n", param->name.c_str(), init_val.bool_val);
//std::cerr << "[InitCond] param is a boolean of with name "
// << param->name << std::endl;
assert(param->engine_val);
*((bool*)param->engine_val) = init_val.bool_val;
return;
}
/* Parameter is an integer type, just like C */
if ( param->type == P_TYPE_INT) {
assert(param->engine_val);
*((int*)param->engine_val) = init_val.int_val;
return;
}
/* Parameter is of a float type, just like C */
if (param->type == P_TYPE_DOUBLE) {
assert(param->engine_val);
*((float*)param->engine_val) = init_val.float_val;
return;
}
/* Unknown type of parameter */
return;
}
/* WIP */
void InitCond::init_cond_to_string() {
int string_length;
char string[MAX_TOKEN_SIZE];
/* Create a string "param_name=val" */
switch (param->type) {
case P_TYPE_BOOL:
sprintf(string, "%s=%d\n", param->name.c_str(), init_val.bool_val);
break;
case P_TYPE_INT:
sprintf(string, "%s=%d\n", param->name.c_str(), init_val.int_val);
break;
case P_TYPE_DOUBLE:
sprintf(string, "%s=%f\n", param->name.c_str(), init_val.float_val);
break;
default:
return;
}
/* Compute the length of the string */
string_length = strlen(string);
/* Buffer overflow check */
if ((init_cond_string_buffer_index + string_length + 1) > (STRING_BUFFER_SIZE - 1))
return;
/* Copy the string into the initial condition string buffer */
strncpy(init_cond_string_buffer + init_cond_string_buffer_index, string, string_length);
/* Increment the string buffer, offset by one for the null terminator, which will be
overwritten by the next call to this function */
init_cond_string_buffer_index+= string_length + 1;
}

View File

@ -0,0 +1,60 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Initial condition
*
* $Log$
*/
#ifndef _INIT_COND_HPP
#define _INIT_COND_HPP
//#define INIT_COND_DEBUG 2
#define INIT_COND_DEBUG 0
#include "Param.hpp"
class InitCond;
class Param;
#include <map>
class InitCond {
public:
Param *param;
CValue init_val;
static char init_cond_string_buffer[STRING_BUFFER_SIZE];
static int init_cond_string_buffer_index;
InitCond( Param * param, CValue init_val);
~InitCond();
void evaluate(); //Wrapper around following declaration
void evaluate(bool evalUser);
void init_cond_to_string();
void write_init();
};
#endif /** !_INIT_COND_H */

View File

@ -0,0 +1,79 @@
#ifndef _INIT_COND_UTILS_HPP
#define _INIT_COND_UTILS_HPP
#include <map>
#include "InitCond.hpp"
#include <iostream>
#include <stdlib.h>
namespace InitCondUtils {
class LoadUnspecInitCond {
public:
LoadUnspecInitCond(std::map<std::string,InitCond*> & initCondTree, std::map<std::string,InitCond*> & perFrameInitEqnTree):
m_initCondTree(initCondTree), m_perFrameInitEqnTree(perFrameInitEqnTree) {}
void operator()(Param * param);
private:
std::map<std::string,InitCond*> & m_initCondTree;
std::map<std::string,InitCond*> & m_perFrameInitEqnTree;
};
inline void LoadUnspecInitCond::operator() (Param * param) {
InitCond * init_cond = 0;
CValue init_val;
assert(param);
assert(param->engine_val);
/* Don't count these parameters as initial conditions */
if (param->flags & P_FLAG_READONLY)
return;
if (param->flags & P_FLAG_QVAR)
return;
// if (param->flags & P_FLAG_TVAR)
// return;
if (param->flags & P_FLAG_USERDEF)
return;
/* If initial condition was not defined by the preset file, force a default one
with the following code */
if (m_initCondTree.find(param->name) == m_initCondTree.end()) {
/* Make sure initial condition does not exist in the set of per frame initial equations */
if (m_perFrameInitEqnTree.find(param->name) != m_perFrameInitEqnTree.end())
return;
// Set an initial vialue via correct union member
if (param->type == P_TYPE_BOOL)
init_val.bool_val = param->default_init_val.bool_val;
else if (param->type == P_TYPE_INT)
init_val.int_val = param->default_init_val.int_val;
else if (param->type == P_TYPE_DOUBLE) {
init_val.float_val = param->default_init_val.float_val;
}
//printf("%s\n", param->name);
/* Create new initial condition */
//std::cerr << "[InitCondUtils] creating an unspecified initial condition of name " << param->name << std::endl;
if ((init_cond = new InitCond(param, init_val)) == NULL) {
abort();
}
/* Insert the initial condition into this presets tree */
std::pair<std::map<std::string, InitCond*>::iterator, bool> inserteePair =
m_initCondTree.insert(std::make_pair(init_cond->param->name, init_cond));
assert(inserteePair.second);
assert(inserteePair.first->second);
} else
assert(m_initCondTree.find(param->name)->second);
}
}
#endif

View File

@ -0,0 +1,554 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#ifdef WIN32
#include "win32-dirent.h"
#else
#include <dirent.h>
#endif /** WIN32 */
#include <time.h>
#include "MilkdropPreset.hpp"
#include "Parser.hpp"
#include "ParamUtils.hpp"
#include "InitCondUtils.hpp"
#include "fatal.h"
#include <iostream>
#include <fstream>
#include "PresetFrameIO.hpp"
MilkdropPreset::MilkdropPreset(std::istream & in, const std::string & presetName, PresetOutputs & presetOutputs):
Preset(presetName),
builtinParams(_presetInputs, presetOutputs),
_presetOutputs(presetOutputs)
{
initialize(in);
}
MilkdropPreset::MilkdropPreset(const std::string & absoluteFilePath, const std::string & presetName, PresetOutputs & presetOutputs):
Preset(presetName),
builtinParams(_presetInputs, presetOutputs),
_absoluteFilePath(absoluteFilePath),
_presetOutputs(presetOutputs),
_filename(parseFilename(absoluteFilePath))
{
initialize(absoluteFilePath);
}
MilkdropPreset::~MilkdropPreset()
{
traverse<TraverseFunctors::Delete<InitCond> >(init_cond_tree);
traverse<TraverseFunctors::Delete<InitCond> >(per_frame_init_eqn_tree);
traverse<TraverseFunctors::Delete<PerPixelEqn> >(per_pixel_eqn_tree);
traverseVector<TraverseFunctors::Delete<PerFrameEqn> >(per_frame_eqn_tree);
traverse<TraverseFunctors::Delete<Param> >(user_param_tree);
/// Testing deletion of render items by the preset. would be nice if it worked,
/// and seems to be working if you use a mutex on the preset switching.
/*
std::cout << "begin freeing of waves / shapes" << std::endl;
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin();
pos != customWaves.end(); ++pos ) {
for (PresetOutputs::cwave_container::iterator pos2 = presetOutputs().customWaves.begin();
pos2 != presetOutputs().customWaves.end(); ++pos2 ) {
if ((*pos2)->id == (*pos)->id)
presetOutputs().customWaves.erase(pos2);
}
delete(*pos);
}
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin();
pos != customShapes.end(); ++pos ) {
for (PresetOutputs::cshape_container::iterator pos2 = presetOutputs().customShapes.begin();
1aaa339f10vmlkd pos2 != presetOutputs().customShapes.end(); ++pos2 ) {
if ((*pos2)->id == (*pos)->id)
presetOutputs().customShapes.erase(pos2);
}
delete(*pos);
}
std::cout << "end freeing of waves / shapes" << std::endl;
*/
}
/* Adds a per pixel equation according to its string name. This
will be used only by the parser */
int MilkdropPreset::add_per_pixel_eqn(char * name, GenExpr * gen_expr)
{
PerPixelEqn * per_pixel_eqn = NULL;
int index;
Param * param = NULL;
assert(gen_expr);
assert(name);
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name);
/* Search for the parameter so we know what matrix the per pixel equation is referencing */
param = ParamUtils::find(name, &this->builtinParams, &this->user_param_tree);
if ( !param )
{
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n");
return PROJECTM_FAILURE;
}
index = per_pixel_eqn_tree.size();
/* Create the per pixel equation given the index, parameter, and general expression */
if ((per_pixel_eqn = new PerPixelEqn(index, param, gen_expr)) == NULL)
{
if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to create new per pixel equation!\n");
return PROJECTM_FAILURE;
}
/* Insert the per pixel equation into the preset per pixel database */
std::pair<std::map<int, PerPixelEqn*>::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert
(std::make_pair(per_pixel_eqn->index, per_pixel_eqn));
if (!inserteeOption.second)
{
printf("failed to add per pixel eqn!\n");
delete(per_pixel_eqn);
return PROJECTM_FAILURE;
}
/* Done */
return PROJECTM_SUCCESS;
}
void MilkdropPreset::evalCustomShapeInitConditions()
{
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) {
assert(*pos);
(*pos)->evalInitConds();
}
}
void MilkdropPreset::evalCustomWaveInitConditions()
{
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) {
assert(*pos);
(*pos)->evalInitConds();
}
}
void MilkdropPreset::evalCustomWavePerFrameEquations()
{
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
{
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
{
assert(_pos->second);
_pos->second->evaluate();
}
std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
{
(*_pos)->evaluate();
}
}
}
void MilkdropPreset::evalCustomShapePerFrameEquations()
{
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
{
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
{
assert(_pos->second);
_pos->second->evaluate();
}
std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
{
(*_pos)->evaluate();
}
}
}
void MilkdropPreset::evalPerFrameInitEquations()
{
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
{
assert(pos->second);
pos->second->evaluate();
}
}
void MilkdropPreset::evalPerFrameEquations()
{
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
{
assert(pos->second);
pos->second->evaluate();
}
for (std::vector<PerFrameEqn*>::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos)
{
(*pos)->evaluate();
}
}
void MilkdropPreset::preloadInitialize() {
/// @note commented this out because it should be unnecessary
// Clear equation trees
//init_cond_tree.clear();
//user_param_tree.clear();
//per_frame_eqn_tree.clear();
//per_pixel_eqn_tree.clear();
//per_frame_init_eqn_tree.clear();
}
void MilkdropPreset::postloadInitialize() {
/* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
this->per_frame_eqn_count = 0;
this->per_frame_init_eqn_count = 0;
this->loadBuiltinParamsUnspecInitConds();
this->loadCustomWaveUnspecInitConds();
this->loadCustomShapeUnspecInitConds();
/// @bug are you handling all the q variables conditions? in particular, the un-init case?
//m_presetOutputs.q1 = 0;
//m_presetOutputs.q2 = 0;
//m_presetOutputs.q3 = 0;
//m_presetOutputs.q4 = 0;
//m_presetOutputs.q5 = 0;
//m_presetOutputs.q6 = 0;
//m_presetOutputs.q7 = 0;
//m_presetOutputs.q8 = 0;
}
void MilkdropPreset::Render(const BeatDetect &music, const PipelineContext &context)
{
_presetInputs.update(music, context);
evaluateFrame();
pipeline().Render(music, context);
}
void MilkdropPreset::initialize(const std::string & pathname)
{
int retval;
preloadInitialize();
if (MILKDROP_PRESET_DEBUG)
std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl;
if ((retval = loadPresetFile(pathname)) < 0)
{
if (MILKDROP_PRESET_DEBUG)
std::cerr << "[Preset] failed to load file \"" <<
pathname << "\"!" << std::endl;
/// @bug how should we handle this problem? a well define exception?
throw retval;
}
postloadInitialize();
}
void MilkdropPreset::initialize(std::istream & in)
{
int retval;
preloadInitialize();
if ((retval = readIn(in)) < 0)
{
if (MILKDROP_PRESET_DEBUG)
std::cerr << "[Preset] failed to load from stream " << std::endl;
/// @bug how should we handle this problem? a well define exception?
throw retval;
}
postloadInitialize();
}
void MilkdropPreset::loadBuiltinParamsUnspecInitConds() {
InitCondUtils::LoadUnspecInitCond loadUnspecInitCond(this->init_cond_tree, this->per_frame_init_eqn_tree);
this->builtinParams.apply(loadUnspecInitCond);
traverse(user_param_tree, loadUnspecInitCond);
}
void MilkdropPreset::loadCustomWaveUnspecInitConds()
{
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
{
assert(*pos);
(*pos)->loadUnspecInitConds();
}
}
void MilkdropPreset::loadCustomShapeUnspecInitConds()
{
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin();
pos != customShapes.end(); ++pos)
{
assert(*pos);
(*pos)->loadUnspecInitConds();
}
}
void MilkdropPreset::evaluateFrame()
{
// Evaluate all equation objects according to milkdrop flow diagram
evalPerFrameInitEquations();
evalPerFrameEquations();
// Important step to ensure custom shapes and waves don't stamp on the q variable values
// calculated by the per frame (init) and per pixel equations.
transfer_q_variables(customWaves);
transfer_q_variables(customShapes);
initialize_PerPixelMeshes();
evalPerPixelEqns();
evalCustomWaveInitConditions();
evalCustomWavePerFrameEquations();
evalCustomShapeInitConditions();
evalCustomShapePerFrameEquations();
// Setup pointers of the custom waves and shapes to the preset outputs instance
/// @slow an extra O(N) per frame, could do this during eval
_presetOutputs.customWaves = PresetOutputs::cwave_container(customWaves);
_presetOutputs.customShapes = PresetOutputs::cshape_container(customShapes);
}
void MilkdropPreset::initialize_PerPixelMeshes()
{
int x,y;
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.cx_mesh[x][y]=presetOutputs().cx;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.cy_mesh[x][y]=presetOutputs().cy;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.sx_mesh[x][y]=presetOutputs().sx;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.sy_mesh[x][y]=presetOutputs().sy;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.dx_mesh[x][y]=presetOutputs().dx;
}}
//std::cout<<presetOutputs().cx<<","<<presetOutputs().cy<<" "<<presetOutputs().dx<<","<<presetOutputs().dy<<std::endl;
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.dy_mesh[x][y]=presetOutputs().dy;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.zoom_mesh[x][y]=presetOutputs().zoom;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.zoomexp_mesh[x][y]=presetOutputs().zoomexp;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.rot_mesh[x][y]=presetOutputs().rot;
}}
for (x=0;x<presetInputs().gx;x++){
for(y=0;y<presetInputs().gy;y++){
_presetOutputs.warp_mesh[x][y]=presetOutputs().warp;
}}
}
// Evaluates all per-pixel equations
void MilkdropPreset::evalPerPixelEqns()
{
/* Evaluate all per pixel equations in the tree datastructure */
for (int mesh_x = 0; mesh_x < presetInputs().gx; mesh_x++)
for (int mesh_y = 0; mesh_y < presetInputs().gy; mesh_y++)
for (std::map<int, PerPixelEqn*>::iterator pos = per_pixel_eqn_tree.begin();
pos != per_pixel_eqn_tree.end(); ++pos)
pos->second->evaluate(mesh_x, mesh_y);
}
int MilkdropPreset::readIn(std::istream & fs) {
line_mode_t line_mode;
presetOutputs().compositeShader.programSource.clear();
presetOutputs().warpShader.programSource.clear();
/* Parse any comments */
if (Parser::parse_top_comment(fs) < 0)
{
if (MILKDROP_PRESET_DEBUG)
std::cerr << "[Preset::readIn] no left bracket found..." << std::endl;
return PROJECTM_FAILURE;
}
/* Parse the preset name and a left bracket */
char tmp_name[MAX_TOKEN_SIZE];
if (Parser::parse_preset_name(fs, tmp_name) < 0)
{
std::cerr << "[Preset::readIn] loading of preset name failed" << std::endl;
return PROJECTM_ERROR;
}
/// @note We ignore the preset name because [preset00] is just not so useful
// Loop through each line in file, trying to succesfully parse the file.
// If a line does not parse correctly, keep trucking along to next line.
int retval;
while ((retval = Parser::parse_line(fs, this)) != EOF)
{
if (retval == PROJECTM_PARSE_ERROR)
{
line_mode = UNSET_LINE_MODE;
// std::cerr << "[Preset::readIn()] parse error in file \"" << this->absoluteFilePath() << "\"" << std::endl;
}
}
// std::cerr << "loadPresetFile: finished line parsing successfully" << std::endl;
/* Now the preset has been loaded.
Evaluation calls can be made at appropiate
times in the frame loop */
return PROJECTM_SUCCESS;
}
/* loadPresetFile: private function that loads a specific preset denoted
by the given pathname */
int MilkdropPreset::loadPresetFile(const std::string & pathname)
{
/* Open the file corresponding to pathname */
std::ifstream fs(pathname.c_str());
if (!fs || fs.eof()) {
if (MILKDROP_PRESET_DEBUG)
std::cerr << "loadPresetFile: loading of file \"" << pathname << "\" failed!\n";
return PROJECTM_ERROR;
}
return readIn(fs);
}
const std::string & MilkdropPreset::name() const {
return name().empty() ? filename() : name();
}

View File

@ -0,0 +1,231 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* MilkdropPreset
*
* $Log$
*/
#ifndef _MilkdropPreset_HPP
#define _MilkdropPreset_HPP
#include "Common.hpp"
#include <string>
#include <cassert>
#include <map>
#define MILKDROP_PRESET_DEBUG 0 /* 0 for no debugging, 1 for normal, 2 for insane */
#include "CustomShape.hpp"
#include "CustomWave.hpp"
#include "Expr.hpp"
#include "PerPixelEqn.hpp"
#include "PerFrameEqn.hpp"
#include "BuiltinParams.hpp"
#include "PresetFrameIO.hpp"
#include "InitCond.hpp"
#include "Preset.hpp"
class CustomWave;
class CustomShape;
class InitCond;
class MilkdropPreset : public Preset
{
public:
/// Load a MilkdropPreset by filename with input and output buffers specified.
/// \param absoluteFilePath the absolute file path of a MilkdropPreset to load from the file system
/// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
/// \param MilkdropPresetInputs a reference to read only projectM engine variables
/// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset
MilkdropPreset(const std::string & absoluteFilePath, const std::string & milkdropPresetName, PresetOutputs & presetOutputs);
/// Load a MilkdropPreset from an input stream with input and output buffers specified.
/// \param in an already initialized input stream to read the MilkdropPreset file from
/// \param MilkdropPresetName a descriptive name for the MilkdropPreset. Usually just the file name
/// \param MilkdropPresetInputs a reference to read only projectM engine variables
/// \param MilkdropPresetOutputs initialized and filled with data parsed from a MilkdropPreset
MilkdropPreset(std::istream & in, const std::string & milkdropPresetName, PresetOutputs & presetOutputs);
~MilkdropPreset();
/// All "builtin" parameters for this MilkdropPreset. Anything *but* user defined parameters and
/// custom waves / shapes objects go here.
/// @bug encapsulate
BuiltinParams builtinParams;
/// Used by parser to find/create custom waves and shapes. May be refactored
template <class CustomObject>
static CustomObject * find_custom_object(int id, std::vector<CustomObject*> & customObjects);
int per_pixel_eqn_string_index;
int per_frame_eqn_string_index;
int per_frame_init_eqn_string_index;
int per_frame_eqn_count,
per_frame_init_eqn_count;
/// Used by parser
/// @bug refactor
int add_per_pixel_eqn( char *name, GenExpr *gen_expr );
/// Accessor method to retrieve the absolute file path of the loaded MilkdropPreset
/// \returns a file path string
std::string absoluteFilePath() const
{
return _absoluteFilePath;
}
/// Accessor method for the MilkdropPreset outputs instance associated with this MilkdropPreset
/// \returns A MilkdropPreset output instance with values computed from most recent evaluateFrame()
PresetOutputs & presetOutputs() const
{
return _presetOutputs;
}
const PresetInputs & presetInputs() const
{
return _presetInputs;
}
// @bug encapsulate
PresetOutputs::cwave_container customWaves;
PresetOutputs::cshape_container customShapes;
/// @bug encapsulate
/* Data structures that contain equation and initial condition information */
std::vector<PerFrameEqn*> per_frame_eqn_tree; /* per frame equations */
std::map<int, PerPixelEqn*> per_pixel_eqn_tree; /* per pixel equation tree */
std::map<std::string,InitCond*> per_frame_init_eqn_tree; /* per frame initial equations */
std::map<std::string,InitCond*> init_cond_tree; /* initial conditions */
std::map<std::string,Param*> user_param_tree; /* user parameter splay tree */
PresetOutputs & pipeline() { return _presetOutputs; }
void Render(const BeatDetect &music, const PipelineContext &context);
const std::string & name() const;
const std::string & filename() const { return _filename; }
private:
std::string _filename;
PresetInputs _presetInputs;
/// Evaluates the MilkdropPreset for a frame given the current values of MilkdropPreset inputs / outputs
/// All calculated values are stored in the associated MilkdropPreset outputs instance
void evaluateFrame();
// The absolute file path of the MilkdropPreset
std::string _absoluteFilePath;
// The absolute path of the MilkdropPreset
std::string _absolutePath;
void initialize(const std::string & pathname);
void initialize(std::istream & in);
int loadPresetFile(const std::string & pathname);
void loadBuiltinParamsUnspecInitConds();
void loadCustomWaveUnspecInitConds();
void loadCustomShapeUnspecInitConds();
void evalCustomWavePerFrameEquations();
void evalCustomShapePerFrameEquations();
void evalPerFrameInitEquations();
void evalCustomWaveInitConditions();
void evalCustomShapeInitConditions();
void evalPerPixelEqns();
void evalPerFrameEquations();
void initialize_PerPixelMeshes();
int readIn(std::istream & fs);
void preloadInitialize();
void postloadInitialize();
PresetOutputs & _presetOutputs;
template <class CustomObject>
void transfer_q_variables(std::vector<CustomObject*> & customObjects);
};
template <class CustomObject>
void MilkdropPreset::transfer_q_variables(std::vector<CustomObject*> & customObjects)
{
CustomObject * custom_object;
for (typename std::vector<CustomObject*>::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) {
custom_object = *pos;
for (unsigned int i = 0; i < NUM_Q_VARIABLES; i++)
custom_object->q[i] = _presetOutputs.q[i];
}
}
template <class CustomObject>
CustomObject * MilkdropPreset::find_custom_object(int id, std::vector<CustomObject*> & customObjects)
{
CustomObject * custom_object = NULL;
for (typename std::vector<CustomObject*>::iterator pos = customObjects.begin(); pos != customObjects.end();++pos) {
if ((*pos)->id == id) {
custom_object = *pos;
break;
}
}
if (custom_object == NULL)
{
if ((custom_object = new CustomObject(id)) == NULL)
{
return NULL;
}
customObjects.push_back(custom_object);
}
assert(custom_object);
return custom_object;
}
#endif /** !_MilkdropPreset_HPP */

View File

@ -0,0 +1,227 @@
//
// C++ Implementation: MilkdropPresetFactory
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
//
#include "MilkdropPresetFactory.hpp"
#include "MilkdropPreset.hpp"
#include "BuiltinFuncs.hpp"
#include "Eval.hpp"
#include "IdlePreset.hpp"
#include "PresetFrameIO.hpp"
MilkdropPresetFactory::MilkdropPresetFactory(int gx, int gy): _usePresetOutputs(false)
{
/* Initializes the builtin function database */
BuiltinFuncs::init_builtin_func_db();
/* Initializes all infix operators */
Eval::init_infix_ops();
_presetOutputs = createPresetOutputs(gx,gy);
_presetOutputs2 = createPresetOutputs(gx, gy);
}
MilkdropPresetFactory::~MilkdropPresetFactory() {
std::cerr << "[~MilkdropPresetFactory] destroy infix ops" << std::endl;
Eval::destroy_infix_ops();
std::cerr << "[~MilkdropPresetFactory] destroy builtin func" << std::endl;
BuiltinFuncs::destroy_builtin_func_db();
std::cerr << "[~MilkdropPresetFactory] delete preset out puts" << std::endl;
delete(_presetOutputs);
delete(_presetOutputs2);
std::cerr << "[~MilkdropPresetFactory] done" << std::endl;
}
/* Reinitializes the engine variables to a default (conservative and sane) value */
void resetPresetOutputs(PresetOutputs *presetOutputs)
{
presetOutputs->zoom=1.0;
presetOutputs->zoomexp = 1.0;
presetOutputs->rot= 0.0;
presetOutputs->warp= 0.0;
presetOutputs->sx= 1.0;
presetOutputs->sy= 1.0;
presetOutputs->dx= 0.0;
presetOutputs->dy= 0.0;
presetOutputs->cx= 0.5;
presetOutputs->cy= 0.5;
presetOutputs->screenDecay=.98;
presetOutputs->wave.r= 1.0;
presetOutputs->wave.g= 0.2;
presetOutputs->wave.b= 0.0;
presetOutputs->wave.x= 0.5;
presetOutputs->wave.y= 0.5;
presetOutputs->wave.mystery= 0.0;
presetOutputs->border.outer_size= 0.0;
presetOutputs->border.outer_r= 0.0;
presetOutputs->border.outer_g= 0.0;
presetOutputs->border.outer_b= 0.0;
presetOutputs->border.outer_a= 0.0;
presetOutputs->border.inner_size = 0.0;
presetOutputs->border.inner_r = 0.0;
presetOutputs->border.inner_g = 0.0;
presetOutputs->border.inner_b = 0.0;
presetOutputs->border.inner_a = 0.0;
presetOutputs->mv.a = 0.0;
presetOutputs->mv.r = 0.0;
presetOutputs->mv.g = 0.0;
presetOutputs->mv.b = 0.0;
presetOutputs->mv.length = 1.0;
presetOutputs->mv.x_num = 16.0;
presetOutputs->mv.y_num = 12.0;
presetOutputs->mv.x_offset = 0.02;
presetOutputs->mv.y_offset = 0.02;
/* PER_FRAME CONSTANTS END */
presetOutputs->fRating = 0;
presetOutputs->fGammaAdj = 1.0;
presetOutputs->videoEcho.zoom = 1.0;
presetOutputs->videoEcho.a = 0;
presetOutputs->videoEcho.orientation = Normal;
presetOutputs->wave.additive = false;
presetOutputs->wave.dots = false;
presetOutputs->wave.thick = false;
presetOutputs->wave.modulateAlphaByVolume = 0;
presetOutputs->wave.maximizeColors = 0;
presetOutputs->textureWrap = 0;
presetOutputs->bDarkenCenter = 0;
presetOutputs->bRedBlueStereo = 0;
presetOutputs->bBrighten = 0;
presetOutputs->bDarken = 0;
presetOutputs->bSolarize = 0;
presetOutputs->bInvert = 0;
presetOutputs->bMotionVectorsOn = 1;
presetOutputs->wave.a =1.0;
presetOutputs->wave.scale = 1.0;
presetOutputs->wave.smoothing = 0;
presetOutputs->wave.mystery = 0;
presetOutputs->wave.modOpacityEnd = 0;
presetOutputs->wave.modOpacityStart = 0;
presetOutputs->fWarpAnimSpeed = 0;
presetOutputs->fWarpScale = 0;
presetOutputs->fShader = 0;
/* PER_PIXEL CONSTANT END */
/* Q VARIABLES START */
for (int i = 0;i< 32;i++)
presetOutputs->q[i] = 0;
// for ( std::vector<CustomWave*>::iterator pos = presetOutputs->customWaves.begin();
// pos != presetOutputs->customWaves.end(); ++pos )
// if ( *pos != 0 ) delete ( *pos );
// for ( std::vector<CustomShape*>::iterator pos = presetOutputs->customShapes.begin();
// pos != presetOutputs->customShapes.end(); ++pos )
// if ( *pos != 0 ) delete ( *pos );
presetOutputs->customWaves.clear();
presetOutputs->customShapes.clear();
/* Q VARIABLES END */
}
/* Reinitializes the engine variables to a default (conservative and sane) value */
void MilkdropPresetFactory::reset()
{
resetPresetOutputs(_presetOutputs);
resetPresetOutputs(_presetOutputs2);
}
PresetOutputs* MilkdropPresetFactory::createPresetOutputs(int gx, int gy)
{
PresetOutputs *presetOutputs = new PresetOutputs();
presetOutputs->Initialize(gx,gy);
/* PER FRAME CONSTANTS BEGIN */
presetOutputs->zoom=1.0;
presetOutputs->zoomexp = 1.0;
presetOutputs->rot= 0.0;
presetOutputs->warp= 0.0;
presetOutputs->sx= 1.0;
presetOutputs->sy= 1.0;
presetOutputs->dx= 0.0;
presetOutputs->dy= 0.0;
presetOutputs->cx= 0.5;
presetOutputs->cy= 0.5;
presetOutputs->screenDecay=.98;
//_presetInputs.meshx = 0;
//_presetInputs.meshy = 0;
/* PER_FRAME CONSTANTS END */
presetOutputs->fRating = 0;
presetOutputs->fGammaAdj = 1.0;
presetOutputs->videoEcho.zoom = 1.0;
presetOutputs->videoEcho.a = 0;
presetOutputs->videoEcho.orientation = Normal;
presetOutputs->textureWrap = 0;
presetOutputs->bDarkenCenter = 0;
presetOutputs->bRedBlueStereo = 0;
presetOutputs->bBrighten = 0;
presetOutputs->bDarken = 0;
presetOutputs->bSolarize = 0;
presetOutputs->bInvert = 0;
presetOutputs->bMotionVectorsOn = 1;
presetOutputs->fWarpAnimSpeed = 0;
presetOutputs->fWarpScale = 0;
presetOutputs->fShader = 0;
/* PER_PIXEL CONSTANTS BEGIN */
/* PER_PIXEL CONSTANT END */
/* Q AND T VARIABLES START */
for (int i = 0;i<NUM_Q_VARIABLES;i++)
presetOutputs->q[i] = 0;
/* Q AND T VARIABLES END */
return presetOutputs;
}
std::auto_ptr<Preset> MilkdropPresetFactory::allocate(const std::string & url, const std::string & name, const std::string & author) {
PresetOutputs *presetOutputs = _usePresetOutputs ? _presetOutputs : _presetOutputs2;
_usePresetOutputs = !_usePresetOutputs;
resetPresetOutputs(presetOutputs);
std::string path;
if (PresetFactory::protocol(url, path) == PresetFactory::IDLE_PRESET_PROTOCOL) {
return IdlePresets::allocate(path, *presetOutputs);
} else
return std::auto_ptr<Preset>(new MilkdropPreset(url, name, *presetOutputs));
}

View File

@ -0,0 +1,43 @@
//
// C++ Interface: MilkdropPresetFactory
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef __MILKDROP_PRESET_FACTORY_HPP
#define __MILKDROP_PRESET_FACTORY_HPP
#include <memory>
#include "../PresetFactory.hpp"
class DLLEXPORT PresetOutputs;
class DLLEXPORT PresetInputs;
class MilkdropPresetFactory : public PresetFactory {
public:
MilkdropPresetFactory(int gx, int gy);
virtual ~MilkdropPresetFactory();
std::auto_ptr<Preset> allocate(const std::string & url, const std::string & name = std::string(),
const std::string & author = std::string());
std::string supportedExtensions() const { return "milk prjm"; }
private:
static PresetOutputs* createPresetOutputs(int gx, int gy);
void reset();
PresetOutputs * _presetOutputs;
PresetOutputs * _presetOutputs2;
bool _usePresetOutputs;
//PresetInputs _presetInputs;
};
#endif

View File

@ -0,0 +1,199 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/* Basic Parameter Functions */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "fatal.h"
#include "Common.hpp"
#include "CustomShape.hpp"
#include "Eval.hpp"
#include "Expr.hpp"
#include "InitCond.hpp"
#include "Param.hpp"
#include "Preset.hpp"
#include <map>
#include <iostream>
#include <cassert>
/** Constructor */
Param::Param( std::string _name, short int _type, short int _flags, void * _engine_val, void * _matrix,
CValue _default_init_val, CValue _upper_bound, CValue _lower_bound):
name(_name),
type(_type),
flags (_flags),
matrix_flag (0),
engine_val(_engine_val),
matrix (_matrix),
default_init_val (_default_init_val),
upper_bound (_upper_bound),
lower_bound (_lower_bound)
{
}
/* Creates a user defined parameter */
Param::Param(std::string _name) :
name(_name),
type(P_TYPE_DOUBLE),
flags(P_FLAG_USERDEF),
matrix_flag(0),
matrix(0)
{
engine_val = new float();
default_init_val.float_val = DEFAULT_DOUBLE_IV;
upper_bound.float_val = DEFAULT_DOUBLE_UB;
lower_bound.float_val = DEFAULT_DOUBLE_LB;
/// @note may have fixed a recent bug. testing
*((float*)engine_val) = default_init_val.float_val;
}
/* Free's a parameter type */
Param::~Param() {
// I hate this, but will let it be for now
if (flags & P_FLAG_USERDEF) {
delete((double*)engine_val);
}
if (PARAM_DEBUG) printf("~Param: freeing \"%s\".\n", name.c_str());
}
/* Returns nonzero if the string is valid parameter name */
bool Param::is_valid_param_string( const char * string ) {
if (string == NULL)
return false;
/* This ensures the first character is non numeric */
if ( ((*string) >= 48) && ((*string) <= 57))
return false;
/* These probably should never happen */
if (*string == '.')
return false;
if (*string == '+')
return false;
if (*string == '-')
return false;
/* Could also add checks for other symbols. May do later */
return true;
}
/* Loads a float parameter into the builtin database */
Param * Param::new_param_float(const char * name, short int flags, void * engine_val, void * matrix,
float upper_bound, float lower_bound, float init_val) {
Param * param;
CValue iv, ub, lb;
assert(engine_val);
iv.float_val = init_val;
ub.float_val = upper_bound;
lb.float_val = lower_bound;
if ((param = new Param(name, P_TYPE_DOUBLE, flags, engine_val, matrix,iv, ub, lb)) == NULL)
return NULL;
/* Finished, return success */
return param;
}
/* Creates a new parameter of type int */
Param * Param::new_param_int(const char * name, short int flags, void * engine_val,
int upper_bound, int lower_bound, int init_val) {
Param * param;
CValue iv, ub, lb;
assert(engine_val);
iv.int_val = init_val;
ub.int_val = upper_bound;
lb.int_val = lower_bound;
if ((param = new Param(name, P_TYPE_INT, flags, engine_val, NULL, iv, ub, lb)) == NULL)
return NULL;
/* Finished, return success */
return param;
}
/* Creates a new parameter of type bool */
Param * Param::new_param_bool(const char * name, short int flags, void * engine_val,
bool upper_bound, bool lower_bound, bool init_val) {
Param * param;
CValue iv, ub, lb;
assert(engine_val);
iv.bool_val = init_val;
ub.bool_val = upper_bound;
lb.bool_val = lower_bound;
if ((param = new Param(name, P_TYPE_BOOL, flags, engine_val, NULL, iv, ub, lb)) == NULL)
return NULL;
/* Finished, return success */
return param;
}
/* Creates a new parameter of type string */
Param * Param::new_param_string(const char * name, short int flags, void * engine_val) {
Param * param;
CValue iv, ub, lb;
assert(engine_val);
iv.bool_val = 0;
ub.bool_val = 0;
lb.bool_val = 0;
if ((param = new Param(name, P_TYPE_STRING, flags, engine_val, NULL, iv, ub, lb)) == NULL)
return NULL;
/* Finished, return success */
return param;
}

View File

@ -0,0 +1,151 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Parameter used within a preset
*
* $Log$
*/
#ifndef _PARAM_H
#define _PARAM_H
/* Debug level, zero for none */
#define PARAM_DEBUG 0
#define P_CREATE 1
#define P_NONE 0
#define P_TYPE_BOOL 0
#define P_TYPE_INT 1
#define P_TYPE_DOUBLE 2
#define P_TYPE_STRING 3
#define P_FLAG_NONE 0
#define P_FLAG_READONLY 1
#define P_FLAG_USERDEF (1 << 1)
#define P_FLAG_QVAR (1 << 2)
#define P_FLAG_TVAR (1 << 3)
#define P_FLAG_ALWAYS_MATRIX (1 << 4)
#define P_FLAG_PER_PIXEL (1 << 6)
#define P_FLAG_PER_POINT (1 << 7)
#include "Expr.hpp"
#include "Common.hpp"
#include <cmath>
#include <string>
class InitCond;
class Param;
class Preset;
//#include <map>
/* Parameter Type */
class Param {
public:
std::string name; /* name of the parameter, not necessary but useful neverthless */
short int type; /* parameter number type (int, bool, or float) */
short int flags; /* read, write, user defined, etc */
short int matrix_flag; /* for optimization purposes */
void * engine_val; /* pointer to the engine variable */
void * matrix; /* per pixel / per point matrix for this variable */
CValue default_init_val; /* a default initial condition value */
CValue upper_bound; /* this parameter's upper bound */
CValue lower_bound; /* this parameter's lower bound */
/// Create a new parameter
Param(std::string name, short int type, short int flags,
void * eqn_val, void *matrix,
CValue default_init_val, CValue upper_bound,
CValue lower_bound);
~Param();
/// Create a user defined floating point parameter
Param( std::string name );
static bool is_valid_param_string( const char *string );
void set_param( float val );
static Param *new_param_float( const char *name, short int flags, void *engine_val,
void *matrix, float upper_bound,
float lower_bound,
float init_val );
static Param *new_param_double(const char *name, short int flags, void *engine_val,
void *matrix, double upper_bound,
double lower_bound,
double init_val );
static Param * new_param_int(const char * name, short int flags, void * engine_val,
int upper_bound, int lower_bound, int init_val );
static Param * new_param_bool(const char * name, short int flags, void * engine_val,
bool upper_bound, bool lower_bound, bool init_val );
static Param * new_param_string(const char * name, short int flags, void * engine_val);
};
/* Sets the parameter engine value to value val.
clipping occurs if necessary */
inline void Param::set_param( float val) {
switch (type) {
case P_TYPE_BOOL:
if (val < 0)
*((bool*)engine_val) = false;
else if (val > 0)
*((bool*)engine_val) = true;
else
*((bool*)engine_val) = false;
break;
case P_TYPE_INT:
/* Make sure value is an integer */
val = floor(val);
if (val < lower_bound.int_val)
*((int*)engine_val) = lower_bound.int_val;
else if (val > upper_bound.int_val)
*((int*)engine_val) = upper_bound.int_val;
else
*((int*)engine_val) = (int)val;
break;
case P_TYPE_DOUBLE:
/* Make sure value is an integer */
if (val < lower_bound.float_val)
*((float*)engine_val) = lower_bound.float_val;
else if (val > upper_bound.float_val)
*((float*)engine_val) = upper_bound.float_val;
else
*((float*)engine_val) = val;
break;
default:
//abort();
break;
}
return;
}
#endif /** !_PARAM_TYPES_H */

View File

@ -0,0 +1,86 @@
/** ParamUtils.hpp:
* A collection of utility functions to make using parameter types easier.
* In reality, this stuff belongs elsewhere, but one step at a time
*/
#ifndef _PARAM_UTILS_HPP
#define _PARAM_UTILS_HPP
#include "Param.hpp"
#include <map>
#include <cassert>
#include "BuiltinParams.hpp"
class ParamUtils
{
public:
static bool insert(Param * param, std::map<std::string,Param*> * paramTree)
{
assert(param);
assert(paramTree);
return ((paramTree->insert(std::make_pair(param->name,param))).second);
}
static const int AUTO_CREATE = 1;
static const int NO_CREATE = 0;
template <int FLAGS>
static Param * find(std::string name, std::map<std::string,Param*> * paramTree)
{
assert(paramTree);
Param * param;
/* First look in the suggested database */
std::map<std::string,Param*>::iterator pos = paramTree->find(name);
if ((FLAGS == AUTO_CREATE) && ((pos == paramTree->end())))
{
/* Check if string is valid */
if (!Param::is_valid_param_string(name.c_str()))
return NULL;
/* Now, create the user defined parameter given the passed name */
if ((param = new Param(name)) == NULL)
return NULL;
/* Finally, insert the new parameter into this preset's parameter tree */
std::pair<std::map<std::string,Param*>::iterator, bool> insertRetPair =
paramTree->insert(std::make_pair(param->name, param));
assert(insertRetPair.second);
} else if (pos != paramTree->end())
param = pos->second;
else
param = NULL;
/* Return the found (or created) parameter. Note that this could be null */
return param;
}
static Param * find(const std::string & name, BuiltinParams * builtinParams, std::map<std::string,Param*> * insertionTree)
{
Param * param;
// Check first db
if ((param = builtinParams->find_builtin_param(name)) != 0)
return param;
// Check second db, create if necessary
return find<AUTO_CREATE>(name, insertionTree);
}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* MilkdropPreset parser
*
* $Log$
*/
#ifndef _PARSER_H
#define _PARSER_H
//#define PARSE_DEBUG 2
#define PARSE_DEBUG 0
#include <stdio.h>
#include "Expr.hpp"
#include "PerFrameEqn.hpp"
#include "InitCond.hpp"
#include "MilkdropPreset.hpp"
/* Strings that prefix (and denote the type of) equations */
#define PER_FRAME_STRING "per_frame_"
#define PER_FRAME_STRING_LENGTH 10
#define PER_PIXEL_STRING "per_pixel_"
#define PER_PIXEL_STRING_LENGTH 10
#define PER_FRAME_INIT_STRING "per_frame_init_"
#define PER_FRAME_INIT_STRING_LENGTH 15
#define WAVECODE_STRING "wavecode_"
#define WAVECODE_STRING_LENGTH 9
#define WAVE_STRING "wave_"
#define WAVE_STRING_LENGTH 5
#define PER_POINT_STRING "per_point"
#define PER_POINT_STRING_LENGTH 9
#define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
#define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
#define SHAPECODE_STRING "shapecode_"
#define SHAPECODE_STRING_LENGTH 10
#define WARP_STRING "warp_"
#define WARP_STRING_LENGTH 5
#define COMPOSITE_STRING "comp_"
#define COMPOSITE_STRING_LENGTH 5
#define SHAPE_STRING "shape_"
#define SHAPE_STRING_LENGTH 6
#define SHAPE_INIT_STRING "init"
#define SHAPE_INIT_STRING_LENGTH 4
#define WAVE_INIT_STRING "init"
#define WAVE_INIT_STRING_LENGTH 4
#include <set>
typedef enum {
UNSET_LINE_MODE,
PER_FRAME_LINE_MODE,
PER_PIXEL_LINE_MODE,
PER_FRAME_INIT_LINE_MODE,
INIT_COND_LINE_MODE,
CUSTOM_WAVE_PER_POINT_LINE_MODE,
CUSTOM_WAVE_PER_FRAME_LINE_MODE,
CUSTOM_WAVE_WAVECODE_LINE_MODE,
CUSTOM_SHAPE_SHAPECODE_LINE_MODE,
CUSTOM_SHAPE_PER_FRAME_LINE_MODE,
CUSTOM_SHAPE_PER_FRAME_INIT_LINE_MODE,
CUSTOM_WAVE_PER_FRAME_INIT_LINE_MODE
} line_mode_t;
/** Token enumeration type */
typedef enum {
tEOL, /* end of a line, usually a '/n' or '/r' */
tEOF, /* end of file */
tLPr, /* ( */
tRPr, /* ) */
tLBr, /* [ */
tRBr, /* ] */
tEq, /* = */
tPlus, /* + */
tMinus, /* - */
tMult, /* * */
tMod, /* % */
tDiv, /* / */
tOr, /* | */
tAnd, /* & */
tComma, /* , */
tPositive, /* + as a prefix operator */
tNegative, /* - as a prefix operator */
tSemiColon, /* ; */
tStringTooLong, /* special token to indicate an invalid string length */
tStringBufferFilled /* the string buffer for this line is maxed out */
} token_t;
class CustomShape;
class CustomWave;
class GenExpr;
class InfixOp;
class PerFrameEqn;
class MilkdropPreset;
class TreeExpr;
class Parser {
public:
static std::string lastLinePrefix;
static line_mode_t line_mode;
static CustomWave *current_wave;
static CustomShape *current_shape;
static int string_line_buffer_index;
static char string_line_buffer[STRING_LINE_SIZE];
static unsigned int line_count;
static int per_frame_eqn_count;
static int per_frame_init_eqn_count;
static int last_custom_wave_id;
static int last_custom_shape_id;
static char last_eqn_type[MAX_TOKEN_SIZE];
static int last_token_size;
static bool tokenWrapAroundEnabled;
static PerFrameEqn *parse_per_frame_eqn( std::istream & fs, int index,
MilkdropPreset * preset);
static int parse_per_pixel_eqn( std::istream & fs, MilkdropPreset * preset,
char * init_string);
static InitCond *parse_init_cond( std::istream & fs, char * name, MilkdropPreset * preset );
static int parse_preset_name( std::istream & fs, char * name );
static int parse_top_comment( std::istream & fs );
static int parse_line( std::istream & fs, MilkdropPreset * preset );
static int get_string_prefix_len(char * string);
static TreeExpr * insert_gen_expr(GenExpr * gen_expr, TreeExpr ** root);
static TreeExpr * insert_infix_op(InfixOp * infix_op, TreeExpr ** root);
static token_t parseToken(std::istream & fs, char * string);
static GenExpr ** parse_prefix_args(std::istream & fs, int num_args, MilkdropPreset * preset);
static GenExpr * parse_infix_op(std::istream & fs, token_t token, TreeExpr * tree_expr, MilkdropPreset * preset);
static GenExpr * parse_sign_arg(std::istream & fs);
static int parse_float(std::istream & fs, float * float_ptr);
static int parse_int(std::istream & fs, int * int_ptr);
static int insert_gen_rec(GenExpr * gen_expr, TreeExpr * root);
static int insert_infix_rec(InfixOp * infix_op, TreeExpr * root);
static GenExpr * parse_gen_expr(std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset);
static PerFrameEqn * parse_implicit_per_frame_eqn(std::istream & fs, char * param_string, int index, MilkdropPreset * preset);
static InitCond * parse_per_frame_init_eqn(std::istream & fs, MilkdropPreset * preset, std::map<std::string,Param*> * database);
static int parse_wavecode_prefix(char * token, int * id, char ** var_string);
static int parse_wavecode(char * token, std::istream & fs, MilkdropPreset * preset);
static int parse_wave_prefix(char * token, int * id, char ** eqn_string);
static int parse_wave_helper(std::istream & fs, MilkdropPreset * preset, int id, char * eqn_type, char * init_string);
static int parse_shapecode(char * eqn_string, std::istream & fs, MilkdropPreset * preset);
static int parse_shapecode_prefix(char * token, int * id, char ** var_string);
static void parse_string_block(std::istream & fs, std::string * out_string);
static bool scanForComment(std::istream & fs);
static int parse_wave(char * eqn_string, std::istream & fs, MilkdropPreset * preset);
static int parse_shape(char * eqn_string, std::istream & fs, MilkdropPreset * preset);
static int parse_shape_prefix(char * token, int * id, char ** eqn_string);
static void readStringUntil(std::istream & fs, std::string * out_buffer, bool wrapAround = true, const std::set<char> & skipList = std::set<char>()) ;
static int string_to_float(char * string, float * float_ptr);
static int parse_shape_per_frame_init_eqn(std::istream & fs, CustomShape * custom_shape, MilkdropPreset * preset);
static int parse_shape_per_frame_eqn(std::istream & fs, CustomShape * custom_shape, MilkdropPreset * preset);
static int parse_wave_per_frame_eqn(std::istream & fs, CustomWave * custom_wave, MilkdropPreset * preset);
static bool wrapsToNextLine(const std::string & str);
};
#endif /** !_PARSER_H */

View File

@ -0,0 +1,67 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fatal.h"
#include "Common.hpp"
#include "Param.hpp"
#include "PerFrameEqn.hpp"
#include "Eval.hpp"
#include "Expr.hpp"
#include "wipemalloc.h"
#include <cassert>
/* Evaluate an equation */
void PerFrameEqn::evaluate() {
if (PER_FRAME_EQN_DEBUG) {
printf("per_frame_%d=%s= ", index, param->name.c_str());
fflush(stdout);
}
//*((float*)per_frame_eqn->param->engine_val) = eval_gen_expr(per_frame_eqn->gen_expr);
assert(gen_expr);
assert(param);
param->set_param(gen_expr->eval_gen_expr(-1,-1));
if (PER_FRAME_EQN_DEBUG) printf(" = %.4f\n", *((float*)param->engine_val));
}
/* Frees perframe equation structure. Warning: assumes gen_expr pointer is not freed by anyone else! */
PerFrameEqn::~PerFrameEqn() {
delete gen_expr;
// param is freed in param_tree container of some other class
}
/* Create a new per frame equation */
PerFrameEqn::PerFrameEqn(int _index, Param * _param, GenExpr * _gen_expr) :
index(_index), param(_param), gen_expr(_gen_expr) {}

View File

@ -0,0 +1,53 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Per-frame equation
*
* $Log$
*/
#ifndef _PER_FRAME_EQN_H
#define _PER_FRAME_EQN_H
#define PER_FRAME_EQN_DEBUG 0
class GenExpr;
class Param;
class PerFrameEqn;
class PerFrameEqn {
public:
int index; /* a unique id for each per frame eqn (generated by order in preset files) */
Param *param; /* parameter to be assigned a value */
GenExpr *gen_expr; /* expression that paremeter is equal to */
PerFrameEqn(int index, Param * param, GenExpr * gen_expr);
~PerFrameEqn();
/// Evaluate the per frame equation
void evaluate();
};
#endif /** !_PER_FRAME_EQN_H */

View File

@ -0,0 +1,74 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include "fatal.h"
#include "Common.hpp"
#include "Expr.hpp"
#include "Eval.hpp"
#include "Param.hpp"
#include "PerPixelEqn.hpp"
#include <map>
#include "wipemalloc.h"
#include <cassert>
/* Evaluates a per pixel equation */
void PerPixelEqn::evaluate(int mesh_i, int mesh_j) {
GenExpr * eqn_ptr = 0;
eqn_ptr = this->gen_expr;
float ** param_matrix = (float**)this->param->matrix;
if (param_matrix == 0) {
assert(param->engine_val);
(*(float*)param->engine_val) = eqn_ptr->eval_gen_expr(mesh_i, mesh_j);
} else {
assert(!(eqn_ptr == NULL || param_matrix == NULL));
param_matrix[mesh_i][mesh_j] = eqn_ptr->eval_gen_expr(mesh_i, mesh_j);
/* Now that this parameter has been referenced with a per
pixel equation, we let the evaluator know by setting
this flag */
/// @bug review and verify this behavior
param->matrix_flag = true;
param->flags |= P_FLAG_PER_PIXEL;
}
}
PerPixelEqn::PerPixelEqn(int _index, Param * _param, GenExpr * _gen_expr):index(_index), param(_param), gen_expr(_gen_expr) {
assert(index >= 0);
assert(param != 0);
assert(gen_expr != 0);
}

View File

@ -0,0 +1,66 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Per-pixel equation
*
* $Log$
*/
#ifndef _PER_PIXEL_EQN_H
#define _PER_PIXEL_EQN_H
#define PER_PIXEL_EQN_DEBUG 0
#define ZOOM_OP 0
#define ZOOMEXP_OP 1
#define ROT_OP 2
#define CX_OP 3
#define CY_OP 4
#define SX_OP 5
#define SY_OP 6
#define DX_OP 7
#define DY_OP 8
#define WARP_OP 9
#define NUM_OPS 10 /* obviously, this number is dependent on the number of existing per pixel operations */
class GenExpr;
class Param;
class PerPixelEqn;
class Preset;
class PerPixelEqn {
public:
int index; /* used for splay tree ordering. */
int flags; /* primarily to specify if this variable is user-defined */
Param *param;
GenExpr *gen_expr;
void evalPerPixelEqns( Preset *preset );
void evaluate(int mesh_i, int mesh_j);
PerPixelEqn(int index, Param * param, GenExpr * gen_expr);
};
#endif /** !_PER_PIXEL_EQN_H */

View File

@ -0,0 +1,91 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cassert>
#include "fatal.h"
#include "Common.hpp"
#include "CustomWave.hpp"
#include "Eval.hpp"
#include "Expr.hpp"
#include "Param.hpp"
#include "PerPixelEqn.hpp"
#include "PerPointEqn.hpp"
#include <map>
#include <iostream>
#include "wipemalloc.h"
/* Evaluates a per point equation for the current custom wave given by interface_wave ptr */
void PerPointEqn::evaluate(int i)
{
float * param_matrix;
GenExpr * eqn_ptr;
// samples = CustomWave::interface_wave->samples;
eqn_ptr = gen_expr;
if (param->matrix == NULL)
{
assert(param->matrix_flag == false);
(*(float*)param->engine_val) = eqn_ptr->eval_gen_expr(i,-1);
return;
}
else
{
param_matrix = (float*)param->matrix;
// -1 is because per points only use one dimension
param_matrix[i] = eqn_ptr->eval_gen_expr(i, -1);
/* Now that this parameter has been referenced with a per
point equation, we let the evaluator know by setting
this flag */
if (!param->matrix_flag)
param->matrix_flag = true;
}
}
PerPointEqn::PerPointEqn(int _index, Param * _param, GenExpr * _gen_expr, int _samples):
index(_index),
samples(_samples),
param(_param),
gen_expr(_gen_expr)
{}
PerPointEqn::~PerPointEqn()
{
delete gen_expr;
}

View File

@ -0,0 +1,53 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Per-point equation
*
* $Log$
*/
#ifndef _PER_POINT_EQN_H
#define _PER_POINT_EQN_H
class CustomWave;
class GenExpr;
class Param;
class PerPointEqn;
class PerPointEqn {
public:
int index;
int samples; // the number of samples to iterate over
Param *param;
GenExpr * gen_expr;
~PerPointEqn();
void evaluate(int i);
PerPointEqn( int index, Param *param, GenExpr *gen_expr, int samples);
};
//inline void eval_per_point_eqn_helper( void *per_point_eqn ) {
// ((PerPointEqn *)per_point_eqn)->evalPerPointEqn();
// }
#endif /** !_PER_POINT_EQN_H */

View File

@ -0,0 +1,575 @@
#include "PresetFrameIO.hpp"
#include "wipemalloc.h"
#include <math.h>
#include <cassert>
#include <iostream>
#include "Renderer/BeatDetect.hpp"
PresetInputs::PresetInputs() : PipelineContext()
{
}
void PresetInputs::update(const BeatDetect & music, const PipelineContext & context) {
// Reflect new values form the beat detection unit
this->bass = music.bass;
this->mid = music.mid;
this->treb = music.treb;
this->bass_att = music.bass_att;
this->mid_att = music.mid_att;
this->treb_att = music.treb_att;
// Reflect new values from the pipeline context
this->fps = context.fps;
this->time = context.time;
this->frame = context.frame;
this->progress = context.progress;
}
void PresetInputs::Initialize ( int gx, int gy )
{
int x, y;
this->gx =gx;
this->gy= gy;
/// @bug no clue if this block belongs here
// ***
progress = 0;
frame = 1;
x_per_pixel = 0;
y_per_pixel = 0;
rad_per_pixel = 0;
ang_per_pixel = 0;
// ***
this->x_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->x_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->y_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x <gx; x++ )
{
this->y_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->rad_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->rad_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->theta_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x <gx; x++ )
{
this->theta_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->origtheta= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->origtheta[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->origrad= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->origrad[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->origx= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->origx[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->origy= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->origy[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
for ( x=0;x<gx;x++ )
{
for ( y=0;y<gy;y++ )
{
this->origx[x][y]=x/ ( float ) ( gx-1 );
this->origy[x][y]=- ( ( y/ ( float ) ( gy-1 ) )-1 );
this->origrad[x][y]=hypot ( ( this->origx[x][y]-.5 ) *2, ( this->origy[x][y]-.5 ) *2 ) * .7071067;
this->origtheta[x][y]=atan2 ( ( ( this->origy[x][y]-.5 ) *2 ), ( ( this->origx[x][y]-.5 ) *2 ) );
}
}
}
PresetOutputs::PresetOutputs() : Pipeline()
{}
PresetOutputs::~PresetOutputs()
{
assert(this->gx > 0);
for ( int x = 0; x < this->gx; x++ )
{
free(this->sx_mesh[x]);
free(this->sy_mesh[x]);
free(this->dy_mesh[x]);
free(this->dx_mesh[x]);
free(this->cy_mesh[x]);
free(this->cx_mesh[x]);
free(this->warp_mesh[x]);
free(this->zoom_mesh[x]);
free(this->zoomexp_mesh[x]);
free(this->rot_mesh[x]);
free(this->orig_x[x]);
free(this->orig_y[x]);
free(this->rad_mesh[x]);
}
free(this->rad_mesh);
free(this->sx_mesh);
free(this->sy_mesh);
free(this->dy_mesh);
free(this->dx_mesh);
free(this->cy_mesh);
free(this->cx_mesh);
free(this->warp_mesh);
free(this->zoom_mesh);
free(this->zoomexp_mesh);
free(this->rot_mesh);
free(this->orig_x);
free(this->orig_y);
}
void PresetOutputs::Render(const BeatDetect &music, const PipelineContext &context)
{
PerPixelMath(context);
drawables.clear();
drawables.push_back(&mv);
for (PresetOutputs::cshape_container::iterator pos = customShapes.begin();
pos != customShapes.end(); ++pos)
{
if( (*pos)->enabled==1) drawables.push_back((*pos));
}
for (PresetOutputs::cwave_container::iterator pos = customWaves.begin();
pos != customWaves.end(); ++pos)
{
if( (*pos)->enabled==1) drawables.push_back((*pos));
}
drawables.push_back(&wave);
if(bDarkenCenter==1) drawables.push_back(&darkenCenter);
drawables.push_back(&border);
compositeDrawables.clear();
compositeDrawables.push_back(&videoEcho);
if (bBrighten==1)
compositeDrawables.push_back(&brighten);
if (bDarken==1)
compositeDrawables.push_back(&darken);
if (bSolarize==1)
compositeDrawables.push_back(&solarize);
if (bInvert==1)
compositeDrawables.push_back(&invert);
}
void PresetOutputs::PerPixelMath(const PipelineContext &context)
{
int x, y;
float fZoom2, fZoom2Inv;
for (x = 0; x < gx; x++)
{
for (y = 0; y < gy; y++)
{
fZoom2 = powf(this->zoom_mesh[x][y], powf(this->zoomexp_mesh[x][y],
rad_mesh[x][y] * 2.0f - 1.0f));
fZoom2Inv = 1.0f / fZoom2;
this->x_mesh[x][y] = this->orig_x[x][y] * 0.5f * fZoom2Inv + 0.5f;
this->y_mesh[x][y] = this->orig_y[x][y] * 0.5f * fZoom2Inv + 0.5f;
}
}
for (x = 0; x < gx; x++)
{
for (y = 0; y < gy; y++)
{
this->x_mesh[x][y] = (this->x_mesh[x][y] - this->cx_mesh[x][y])
/ this->sx_mesh[x][y] + this->cx_mesh[x][y];
}
}
for (x = 0; x < gx; x++)
{
for (y = 0; y < gy; y++)
{
this->y_mesh[x][y] = (this->y_mesh[x][y] - this->cy_mesh[x][y])
/ this->sy_mesh[x][y] + this->cy_mesh[x][y];
}
}
float fWarpTime = context.time * this->fWarpAnimSpeed;
float fWarpScaleInv = 1.0f / this->fWarpScale;
float f[4];
f[0] = 11.68f + 4.0f * cosf(fWarpTime * 1.413f + 10);
f[1] = 8.77f + 3.0f * cosf(fWarpTime * 1.113f + 7);
f[2] = 10.54f + 3.0f * cosf(fWarpTime * 1.233f + 3);
f[3] = 11.49f + 4.0f * cosf(fWarpTime * 0.933f + 5);
for (x = 0; x < gx; x++)
{
for (y = 0; y < gy; y++)
{
this->x_mesh[x][y] += this->warp_mesh[x][y] * 0.0035f * sinf(fWarpTime * 0.333f
+ fWarpScaleInv * (this->orig_x[x][y] * f[0] - this->orig_y[x][y] * f[3]));
this->y_mesh[x][y] += this->warp_mesh[x][y] * 0.0035f * cosf(fWarpTime * 0.375f
- fWarpScaleInv * (this->orig_x[x][y] * f[2] + this->orig_y[x][y] * f[1]));
this->x_mesh[x][y] += this->warp_mesh[x][y] * 0.0035f * cosf(fWarpTime * 0.753f
- fWarpScaleInv * (this->orig_x[x][y] * f[1] - this->orig_y[x][y] * f[2]));
this->y_mesh[x][y] += this->warp_mesh[x][y] * 0.0035f * sinf(fWarpTime * 0.825f
+ fWarpScaleInv * (this->orig_x[x][y] * f[0] + this->orig_y[x][y] * f[3]));
}
}
for (x = 0; x < gx; x++)
{
for (y = 0; y < gy; y++)
{
float u2 = this->x_mesh[x][y] - this->cx_mesh[x][y];
float v2 = this->y_mesh[x][y] - this->cy_mesh[x][y];
float cos_rot = cosf(this->rot_mesh[x][y]);
float sin_rot = sinf(this->rot_mesh[x][y]);
this->x_mesh[x][y] = u2 * cos_rot - v2 * sin_rot + this->cx_mesh[x][y];
this->y_mesh[x][y] = u2 * sin_rot + v2 * cos_rot + this->cy_mesh[x][y];
}
}
for (x = 0; x < gx; x++)
for (y = 0; y < gy; y++)
this->x_mesh[x][y] -= this->dx_mesh[x][y];
for (x = 0; x < gx; x++)
for (y = 0; y < gy; y++)
this->y_mesh[x][y] -= this->dy_mesh[x][y];
}
void PresetOutputs::Initialize ( int gx, int gy )
{
assert(gx > 0);
this->gx = gx;
this->gy= gy;
staticPerPixel = true;
setStaticPerPixel(gx,gy);
assert(this->gx > 0);
int x;
this->x_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->x_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->y_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->y_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->sx_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->sx_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->sy_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->sy_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->dx_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->dx_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->dy_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->dy_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->cx_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->cx_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->cy_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->cy_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->zoom_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->zoom_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->zoomexp_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->zoomexp_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->rot_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->rot_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->warp_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->warp_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->rad_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( x = 0; x < gx; x++ )
{
this->rad_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->orig_x = (float **) wipemalloc(gx * sizeof(float *));
for (x = 0; x < gx; x++)
{
this->orig_x[x] = (float *) wipemalloc(gy * sizeof(float));
}
this->orig_y = (float **) wipemalloc(gx * sizeof(float *));
for (x = 0; x < gx; x++)
{
this->orig_y[x] = (float *) wipemalloc(gy * sizeof(float));
}
//initialize reference grid values
for (x = 0; x < gx; x++)
{
for (int y = 0; y < gy; y++)
{
float origx = x / (float) (gx - 1);
float origy = -((y / (float) (gy - 1)) - 1);
rad_mesh[x][y]=hypot ( ( origx-.5 ) *2, ( origy-.5 ) *2 ) * .7071067;
orig_x[x][y] = (origx - .5) * 2;
orig_y[x][y] = (origy - .5) * 2;
}
}
}
PresetInputs::~PresetInputs()
{
for ( int x = 0; x < this->gx; x++ )
{
free ( this->origtheta[x] );
free ( this->origrad[x] );
free ( this->origx[x] );
free ( this->origy[x] );
free ( this->x_mesh[x] );
free ( this->y_mesh[x] );
free ( this->rad_mesh[x] );
free ( this->theta_mesh[x] );
}
free ( this->origx );
free ( this->origy );
free ( this->origrad );
free ( this->origtheta );
free ( this->x_mesh );
free ( this->y_mesh );
free ( this->rad_mesh );
free ( this->theta_mesh );
this->origx = NULL;
this->origy = NULL;
this->origtheta = NULL;
this->origrad = NULL;
this->x_mesh = NULL;
this->y_mesh = NULL;
this->rad_mesh = NULL;
this->theta_mesh = NULL;
}
void PresetInputs::resetMesh()
{
int x,y;
assert ( x_mesh );
assert ( y_mesh );
assert ( rad_mesh );
assert ( theta_mesh );
for ( x=0;x<this->gx;x++ )
{
for ( y=0;y<this->gy;y++ )
{
x_mesh[x][y]=this->origx[x][y];
y_mesh[x][y]=this->origy[x][y];
rad_mesh[x][y]=this->origrad[x][y];
theta_mesh[x][y]=this->origtheta[x][y];
}
}
}
#ifdef USE_MERGE_PRESET_CODE
void PresetMerger::MergePresets(PresetOutputs & A, PresetOutputs & B, double ratio, int gx, int gy)
{
double invratio = 1.0 - ratio;
//Merge Simple Waveforms
//
// All the mess is because of Waveform 7, which is two lines.
//
//Merge Custom Shapes and Custom Waves
for (PresetOutputs::cshape_container::iterator pos = A.customShapes.begin();
pos != A.customShapes.end(); ++pos)
{
(*pos)->a *= invratio;
(*pos)->a2 *= invratio;
(*pos)->border_a *= invratio;
}
for (PresetOutputs::cshape_container::iterator pos = B.customShapes.begin();
pos != B.customShapes.end(); ++pos)
{
(*pos)->a *= ratio;
(*pos)->a2 *= ratio;
(*pos)->border_a *= ratio;
A.customShapes.push_back(*pos);
}
for (PresetOutputs::cwave_container::iterator pos = A.customWaves.begin();
pos != A.customWaves.end(); ++pos)
{
(*pos)->a *= invratio;
for (int x=0; x < (*pos)->samples; x++)
{
(*pos)->a_mesh[x]= (*pos)->a_mesh[x]*invratio;
}
}
for (PresetOutputs::cwave_container::iterator pos = B.customWaves.begin();
pos != B.customWaves.end(); ++pos)
{
(*pos)->a *= ratio;
for (int x=0; x < (*pos)->samples; x++)
{
(*pos)->a_mesh[x]= (*pos)->a_mesh[x]*ratio;
}
A.customWaves.push_back(*pos);
}
//Interpolate Per-Pixel mesh
for (int x=0;x<gx;x++)
{
for(int y=0;y<gy;y++)
{
A.x_mesh[x][y] = A.x_mesh[x][y]* invratio + B.x_mesh[x][y]*ratio;
}
}
for (int x=0;x<gx;x++)
{
for(int y=0;y<gy;y++)
{
A.y_mesh[x][y] = A.y_mesh[x][y]* invratio + B.y_mesh[x][y]*ratio;
}
}
//Interpolate PerFrame floats
A.screenDecay = A.screenDecay * invratio + B.screenDecay * ratio;
A.wave.r = A.wave.r* invratio + B.wave.r*ratio;
A.wave.g = A.wave.g* invratio + B.wave.g*ratio;
A.wave.b = A.wave.b* invratio + B.wave.b*ratio;
A.wave.a = A.wave.a* invratio + B.wave.a*ratio;
A.wave.x = A.wave.x* invratio + B.wave.x*ratio;
A.wave.y = A.wave.y* invratio + B.wave.y*ratio;
A.wave.mystery = A.wave.mystery* invratio + B.wave.mystery*ratio;
A.border.outer_size = A.border.outer_size* invratio + B.border.outer_size*ratio;
A.border.outer_r = A.border.outer_r* invratio + B.border.outer_r*ratio;
A.border.outer_g = A.border.outer_g* invratio + B.border.outer_g*ratio;
A.border.outer_b = A.border.outer_b* invratio + B.border.outer_b*ratio;
A.border.outer_a = A.border.outer_a* invratio + B.border.outer_a*ratio;
A.border.inner_size = A.border.inner_size* invratio + B.border.inner_size*ratio;
A.border.inner_r = A.border.inner_r* invratio + B.border.inner_r*ratio;
A.border.inner_g = A.border.inner_g* invratio + B.border.inner_g*ratio;
A.border.inner_b = A.border.inner_b* invratio + B.border.inner_b*ratio;
A.border.inner_a = A.border.inner_a* invratio + B.border.inner_a*ratio;
A.mv.a = A.mv.a* invratio + B.mv.a*ratio;
A.mv.r = A.mv.r* invratio + B.mv.r*ratio;
A.mv.g = A.mv.g* invratio + B.mv.g*ratio;
A.mv.b = A.mv.b* invratio + B.mv.b*ratio;
A.mv.length = A.mv.length* invratio + B.mv.length*ratio;
A.mv.x_num = A.mv.x_num* invratio + B.mv.x_num*ratio;
A.mv.y_num = A.mv.y_num* invratio + B.mv.y_num*ratio;
A.mv.y_offset = A.mv.y_offset* invratio + B.mv.y_offset*ratio;
A.mv.x_offset = A.mv.x_offset* invratio + B.mv.x_offset*ratio;
A.fRating = A.fRating* invratio + B.fRating*ratio;
A.fGammaAdj = A.fGammaAdj* invratio + B.fGammaAdj*ratio;
A.videoEcho.zoom = A.videoEcho.zoom* invratio + B.videoEcho.zoom*ratio;
A.videoEcho.a = A.videoEcho.a* invratio + B.videoEcho.a*ratio;
A.fWarpAnimSpeed = A.fWarpAnimSpeed* invratio + B.fWarpAnimSpeed*ratio;
A.fWarpScale = A.fWarpScale* invratio + B.fWarpScale*ratio;
A.fShader = A.fShader* invratio + B.fShader*ratio;
//Switch bools and discrete values halfway. Maybe we should do some interesting stuff here.
if (ratio > 0.5)
{
A.videoEcho.orientation = B.videoEcho.orientation;
A.textureWrap = B.textureWrap;
A.bDarkenCenter = B.bDarkenCenter;
A.bRedBlueStereo = B.bRedBlueStereo;
A.bBrighten = B.bBrighten;
A.bDarken = B.bDarken;
A.bSolarize = B.bSolarize;
A.bInvert = B.bInvert;
A.bMotionVectorsOn = B.bMotionVectorsOn;
}
return;
}
#endif

View File

@ -0,0 +1,144 @@
#ifndef PRESET_FRAME_IO_HPP
#define PRESET_FRAME_IO_HPP
#include <vector>
#include "Renderer/MilkdropWaveform.hpp"
#include "Renderer/Pipeline.hpp"
#include "Renderer/Filters.hpp"
#include "CustomShape.hpp"
#include "CustomWave.hpp"
#include "Renderer/VideoEcho.hpp"
/// Container for all *read only* engine variables a preset requires to
/// evaluate milkdrop equations. Every preset object needs a reference to one of these.
class PresetInputs : public PipelineContext {
public:
/* PER_PIXEL VARIBLES BEGIN */
float x_per_pixel;
float y_per_pixel;
float rad_per_pixel;
float ang_per_pixel;
/* PER_PIXEL VARIBLES END */
float bass;
float mid;
float treb;
float bass_att;
float mid_att;
float treb_att;
/* variables were added in milkdrop 1.04 */
int gx, gy;
float **x_mesh;
float **y_mesh;
float **rad_mesh;
float **theta_mesh;
float **origtheta; //grid containing interpolated mesh reference values
float **origrad;
float **origx; //original mesh
float **origy;
void resetMesh();
~PresetInputs();
PresetInputs();
/// Initializes this preset inputs given a mesh size.
/// \param gx the width of the mesh
/// \param gy the height of the mesh
/// \note This must be called before reading values from this class
void Initialize(int gx, int gy);
/// Updates this preset inputs with the latest values from the
/// the pipeline context and beat detection unit
void update (const BeatDetect & music, const PipelineContext & context);
private:
};
/// Container class for all preset writeable engine variables. This is the important glue
/// between the presets and renderer to facilitate smooth preset switching
/// Every preset object needs a reference to one of these.
class PresetOutputs : public Pipeline {
public:
typedef std::vector<CustomWave*> cwave_container;
typedef std::vector<CustomShape*> cshape_container;
cwave_container customWaves;
cshape_container customShapes;
void Initialize(int gx, int gy);
PresetOutputs();
~PresetOutputs();
virtual void Render(const BeatDetect &music, const PipelineContext &context);
void PerPixelMath( const PipelineContext &context);
/* PER FRAME VARIABLES BEGIN */
float zoom;
float zoomexp;
float rot;
float warp;
float sx;
float sy;
float dx;
float dy;
float cx;
float cy;
VideoEcho videoEcho;
MilkdropWaveform wave;
Border border;
MotionVectors mv;
DarkenCenter darkenCenter;
Brighten brighten;
Darken darken;
Invert invert;
Solarize solarize;
int gy,gx;
/* PER_FRAME VARIABLES END */
float fRating;
float fGammaAdj;
bool bDarkenCenter;
bool bRedBlueStereo;
bool bBrighten;
bool bDarken;
bool bSolarize;
bool bInvert;
bool bMotionVectorsOn;
float fWarpAnimSpeed;
float fWarpScale;
float fShader;
float **zoom_mesh;
float **zoomexp_mesh;
float **rot_mesh;
float **sx_mesh;
float **sy_mesh;
float **dx_mesh;
float **dy_mesh;
float **cx_mesh;
float **cy_mesh;
float **warp_mesh;
float **orig_x; //original mesh
float **orig_y;
float **rad_mesh;
};
#endif

View File

@ -0,0 +1,23 @@
PROJECT(NativePresetFactory)
cmake_minimum_required(VERSION 2.4.0)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
SET(NativePresetFactory_SOURCES NativePresetFactory.cpp)
IF(NOT MSVC)
SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
ENDIF(NOT MSVC)
if(MSVC)
SET (MATH_LIBRARIES )
else(MSVC)
SET (MATH_LIBRARIES m)
endif(MSVC)
INCLUDE_DIRECTORIES(${projectM_SOURCE_DIR} ${Renderer_SOURCE_DIR})
ADD_LIBRARY(NativePresetFactory STATIC ${NativePresetFactory_SOURCES})
SET_TARGET_PROPERTIES(NativePresetFactory PROPERTIES VERSION 2.00 SOVERSION 2)
TARGET_LINK_LIBRARIES(NativePresetFactory Renderer ${MATH_LIBRARIES})

View File

@ -0,0 +1,42 @@
/*
* MilkdropCompatability.hpp
*
* Created on: Jun 18, 2008
* Author: pete
*/
#ifndef MILKDROPCOMPATABILITY_HPP_
#define MILKDROPCOMPATABILITY_HPP_
inline float sign(float a)
{
return a < 0.0 ? -1.0 : 1.0;
}
inline float above(float a, float b)
{
return a > b ? 1 : 0;
}
inline float equal(float a, float b)
{
return a == b ? 1 : 0;
}
inline float below(float a, float b)
{
return a < b ? 1 : 0;
}
inline float min(float a, float b)
{
return a < b ? a : b;
}
inline float max(float a, float b)
{
return a > b ? a : b;
}
inline float if_milk(float a, float b, float c)
{
return (a==1.0) ? b : c;
}
#endif /* MILKDROPCOMPATABILITY_HPP_ */

View File

@ -0,0 +1,38 @@
/*
* Preset.hpp
*
* Created on: Aug 5, 2008
* Author: carm
*/
#ifndef __NATIVE_PRESET_HPP_
#define __NATIVE_PRESET_HPP_
#include <string>
#include "BeatDetect.hpp"
#include "Pipeline.hpp"
#include "PipelineContext.hpp"
#include "Preset.hpp"
/// A templated preset class to build different various hard coded presets and
/// compile them into object files to be loaded into a playlist
template <class PipelineT>
class NativePreset : public Preset {
public:
inline NativePreset(const std::string & name=std::string(),
const std::string & author = std::string()) : Preset(name, author) {}
virtual ~NativePreset() {}
inline PipelineT & pipeline() { return _pipeline; }
inline virtual void Render(const BeatDetect &music, const PipelineContext &context) {
_pipeline.Render(music, context);
}
private:
PipelineT _pipeline;
};
#endif

View File

@ -0,0 +1,116 @@
//
// C++ Implementation: NativePresetFactory
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <dlfcn.h>
#include "NativePresetFactory.hpp"
typedef void Handle;
typedef void DestroyFunctor(Preset*);
typedef Preset * CreateFunctor(const char * url);
class LibraryPreset : public Preset {
public:
LibraryPreset(Preset * preset, DestroyFunctor * destroyFun) : Preset(preset->name(), preset->author()), _internalPreset(preset), _destroyFunctor(destroyFun) {}
inline Pipeline & pipeline() { return _internalPreset->pipeline(); }
inline virtual ~LibraryPreset() { _destroyFunctor(_internalPreset); }
inline void Render(const BeatDetect &music, const PipelineContext &context) {
return _internalPreset->Render(music, context);
}
private:
Preset * _internalPreset;
DestroyFunctor * _destroyFunctor;
};
class PresetLibrary {
public:
PresetLibrary(Handle * h, CreateFunctor * create, DestroyFunctor * destroy) :
_handle(h), _createFunctor(create), _destroyFunctor(destroy) {}
Handle * handle() { return _handle; }
CreateFunctor * createFunctor() { return _createFunctor; }
DestroyFunctor * destroyFunctor() { return _destroyFunctor; }
~PresetLibrary() {
dlclose(handle());
}
private:
Handle * _handle;
CreateFunctor * _createFunctor;
DestroyFunctor * _destroyFunctor;
};
NativePresetFactory::NativePresetFactory() {}
NativePresetFactory::~NativePresetFactory() {
for (PresetLibraryMap::iterator pos = _libraries.begin(); pos != _libraries.end(); ++pos) {
std::cerr << "deleting preset library" << std::endl;
delete(pos->second);
}
}
PresetLibrary * NativePresetFactory::loadLibrary(const std::string & url) {
if (_libraries.count(url))
return _libraries[url];
// load the preset library
void* handle = dlopen(url.c_str(), RTLD_LAZY);
if (!handle) {
std::cerr << "[NativePresetFactory] Cannot load library: " << dlerror() << '\n';
return 0;
}
// reset errors
dlerror();
// load the symbols
CreateFunctor * create = (CreateFunctor*) dlsym(handle, "create");
const char * dlsym_error = dlerror();
if (dlsym_error) {
std::cerr << "[NativePresetFactory] Cannot load symbol create: " << dlsym_error << '\n';
return 0;
}
DestroyFunctor * destroy = (DestroyFunctor*) dlsym(handle, "destroy");
dlsym_error = dlerror();
if (dlsym_error) {
std::cerr << "[NativePresetFactory] Cannot load symbol destroy: " << dlsym_error << '\n';
return 0;
}
std::cerr << "[NativePresetFactory] creating preset library from url " << url << std::endl;
PresetLibrary * library = new PresetLibrary(handle, create, destroy);
_libraries.insert(std::make_pair(url, library));
return library;
}
std::auto_ptr<Preset> NativePresetFactory::allocate
(const std::string & url, const std::string & name, const std::string & author) {
PresetLibrary * library;
if ((library = loadLibrary(url)) == 0)
return std::auto_ptr<Preset>(0);
return std::auto_ptr<Preset>(new LibraryPreset
(library->createFunctor()(url.c_str()), library->destroyFunctor()));
}

View File

@ -0,0 +1,41 @@
//
// C++ Interface: NativePresetFactory
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef __NATIVE_PRESET_FACTORY_HPP
#define __NATIVE_PRESET_FACTORY_HPP
#include <memory>
#include "PresetFactory.hpp"
class PresetLibrary;
class NativePresetFactory : public PresetFactory {
public:
NativePresetFactory();
virtual ~NativePresetFactory();
virtual std::auto_ptr<Preset> allocate(const std::string & url, const std::string & name = std::string(),
const std::string & author = std::string());
virtual std::string supportedExtensions() const { return "so"; }
private:
PresetLibrary * loadLibrary(const std::string & url);
typedef std::map<std::string, PresetLibrary*> PresetLibraryMap;
PresetLibraryMap _libraries;
};
#endif

361
3rdparty/libprojectm/PCM.cpp vendored Executable file
View File

@ -0,0 +1,361 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id: PCM.c,v 1.3 2006/03/13 20:35:26 psperl Exp $
*
* Takes sound data from wherever and hands it back out.
* Returns PCM Data or spectrum data, or the derivative of the PCM data
*/
#include <stdlib.h>
#include <stdio.h>
#include "Common.hpp"
#include "wipemalloc.h"
#include "fftsg.h"
#include "PCM.hpp"
#include <cassert>
int PCM::maxsamples = 2048;
//initPCM(int samples)
//
//Initializes the PCM buffer to
// number of samples specified.
#include <iostream>
PCM::PCM() {
initPCM( 2048 );
#ifdef DEBUG
std::cerr << "[PCM] MAX SAMPLES:" << maxsamples << std::endl;
#endif
}
void PCM::initPCM(int samples) {
int i;
waveSmoothing = 0;
//Allocate memory for PCM data buffer
assert(samples == 2048);
PCMd = (float **)wipemalloc(2 * sizeof(float *));
PCMd[0] = (float *)wipemalloc(samples * sizeof(float));
PCMd[1] = (float *)wipemalloc(samples * sizeof(float));
//maxsamples=samples;
newsamples=0;
numsamples = maxsamples;
//Initialize buffers to 0
for (i=0;i<samples;i++)
{
PCMd[0][i]=0;
PCMd[1][i]=0;
}
start=0;
//Allocate FFT workspace
w= (double *)wipemalloc(maxsamples*sizeof(double));
ip= (int *)wipemalloc(maxsamples*sizeof(int));
ip[0]=0;
/** PCM data */
// this->maxsamples = 2048;
// this->numsamples = 0;
// this->pcmdataL = NULL;
// this->pcmdataR = NULL;
/** Allocate PCM data structures */
pcmdataL=(float *)wipemalloc(this->maxsamples*sizeof(float));
pcmdataR=(float *)wipemalloc(this->maxsamples*sizeof(float));
}
PCM::~PCM() {
free(pcmdataL);
free(pcmdataR);
free(w);
free(ip);
free(PCMd[0]);
free(PCMd[1]);
free(PCMd);
}
#include <iostream>
void PCM::addPCMfloat(const float *PCMdata, int samples)
{
int i,j;
for(i=0;i<samples;i++)
{
j=i+start;
if (PCMdata[i] != 0 ) {
PCMd[0][j%maxsamples] = PCMdata[i];
PCMd[1][j%maxsamples] = PCMdata[i];
}
else
{
PCMd[0][j % maxsamples] = 0;
PCMd[1][j % maxsamples] = 0;
}
}
start+=samples;
start=start%maxsamples;
newsamples+=samples;
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
}
void PCM::addPCM16Data(const short* pcm_data, short samples) {
int i, j;
for (i = 0; i < samples; ++i) {
j=i+start;
PCMd[0][j % maxsamples]=(pcm_data[i * 2 + 0]/16384.0);
PCMd[1][j % maxsamples]=(pcm_data[i * 2 + 1]/16384.0);
}
start = (start + samples) % maxsamples;
newsamples+=samples;
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
}
void PCM::addPCM16(short PCMdata[2][512])
{
int i,j;
int samples=512;
for(i=0;i<samples;i++)
{
j=i+start;
if ( PCMdata[0][i] != 0 && PCMdata[1][i] != 0 ) {
PCMd[0][j%maxsamples]=(PCMdata[0][i]/16384.0);
PCMd[1][j%maxsamples]=(PCMdata[1][i]/16384.0);
} else {
PCMd[0][j % maxsamples] = (float)0;
PCMd[1][j % maxsamples] = (float)0;
}
}
// printf("Added %d samples %d %d %f\n",samples,start,(start+samples)%maxsamples,PCM[0][start+10]);
start+=samples;
start=start%maxsamples;
newsamples+=samples;
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
}
void PCM::addPCM8( unsigned char PCMdata[2][1024])
{
int i,j;
int samples=1024;
for(i=0;i<samples;i++)
{
j=i+start;
if ( PCMdata[0][i] != 0 && PCMdata[1][i] != 0 ) {
PCMd[0][j%maxsamples]=( (float)( PCMdata[0][i] - 128.0 ) / 64 );
PCMd[1][j%maxsamples]=( (float)( PCMdata[1][i] - 128.0 ) / 64 );
} else {
PCMd[0][j % maxsamples] = 0;
PCMd[1][j % maxsamples] = 0;
}
}
// printf("Added %d samples %d %d %f\n",samples,start,(start+samples)%maxsamples,PCM[0][start+10]);
start+=samples;
start=start%maxsamples;
newsamples+=samples;
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
}
void PCM::addPCM8_512( const unsigned char PCMdata[2][512])
{
int i,j;
int samples=512;
for(i=0;i<samples;i++)
{
j=i+start;
if ( PCMdata[0][i] != 0 && PCMdata[1][i] != 0 ) {
PCMd[0][j%maxsamples]=( (float)( PCMdata[0][i] - 128.0 ) / 64 );
PCMd[1][j%maxsamples]=( (float)( PCMdata[1][i] - 128.0 ) / 64 );
} else {
PCMd[0][j % maxsamples] = 0;
PCMd[1][j % maxsamples] = 0;
}
}
// printf("Added %d samples %d %d %f\n",samples,start,(start+samples)%maxsamples,PCM[0][start+10]);
start+=samples;
start=start%maxsamples;
newsamples+=samples;
if (newsamples>maxsamples) newsamples=maxsamples;
numsamples = getPCMnew(pcmdataR,1,0,waveSmoothing,0,0);
getPCMnew(pcmdataL,0,0,waveSmoothing,0,1);
getPCM(vdataL,512,0,1,0,0);
getPCM(vdataR,512,1,1,0,0);
}
//puts sound data requested at provided pointer
//
//samples is number of PCM samples to return
//freq = 0 gives PCM data
//freq = 1 gives FFT data
//smoothing is the smoothing coefficient
//returned values are normalized from -1 to 1
void PCM::getPCM(float *PCMdata, int samples, int channel, int freq, float smoothing, int derive)
{
int i,index;
index=start-1;
if (index<0) index=maxsamples+index;
PCMdata[0]=PCMd[channel][index];
for(i=1;i<samples;i++)
{
index=start-1-i;
if (index<0) index=maxsamples+index;
PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
}
//return derivative of PCM data
if(derive)
{
for(i=0;i<samples-1;i++)
{
PCMdata[i]=PCMdata[i]-PCMdata[i+1];
}
PCMdata[samples-1]=0;
}
//return frequency data instead of PCM (perform FFT)
if (freq)
{
double temppcm[1024];
for (int i=0;i<samples;i++)
{temppcm[i]=(double)PCMdata[i];}
rdft(samples, 1, temppcm, ip, w);
for (int j=0;j<samples;j++)
{PCMdata[j]=(float)temppcm[j];}
}
}
//getPCMnew
//
//Like getPCM except it returns all new samples in the buffer
//the actual return value is the number of samples, up to maxsamples.
//the passed pointer, PCMData, must bee able to hold up to maxsamples
int PCM::getPCMnew(float *PCMdata, int channel, int freq, float smoothing, int derive, int reset)
{
int i,index;
index=start-1;
if (index<0) index=maxsamples+index;
PCMdata[0]=PCMd[channel][index];
for(i=1;i<newsamples;i++)
{
index=start-1-i;
if (index<0) index=maxsamples+index;
PCMdata[i]=(1-smoothing)*PCMd[channel][index]+smoothing*PCMdata[i-1];
}
//return derivative of PCM data
if(derive)
{
for(i=0;i<newsamples-1;i++)
{
PCMdata[i]=PCMdata[i]-PCMdata[i+1];
}
PCMdata[newsamples-1]=0;
}
//return frequency data instead of PCM (perform FFT)
// if (freq) rdft(samples, 1, PCMdata, ip, w);
i=newsamples;
if (reset) newsamples=0;
return i;
}
//Free stuff
void PCM::freePCM() {
free(PCMd[0]);
free(PCMd[1]);
free(PCMd);
free(ip);
free(w);
PCMd = NULL;
ip = NULL;
w = NULL;
}

74
3rdparty/libprojectm/PCM.hpp vendored Executable file
View File

@ -0,0 +1,74 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Encapsulation of raw sound buffer. Used in beat detection
*
* $Log$
*/
#ifndef _PCM_H
#define _PCM_H
#include "dlldefs.h"
class
#ifdef WIN32
DLLEXPORT
#endif
PCM {
public:
float **PCMd;
int start;
/** Use wave smoothing */
float waveSmoothing;
int *ip;
double *w;
int newsamples;
int numsamples; //size of new PCM info
float *pcmdataL; //holder for most recent pcm data
float *pcmdataR; //holder for most recent pcm data
/** PCM data */
float vdataL[512]; //holders for FFT data (spectrum)
float vdataR[512];
static int maxsamples;
PCM();
~PCM();
void initPCM(int maxsamples);
void addPCMfloat(const float *PCMdata, int samples);
void addPCM16(short [2][512]);
void addPCM16Data(const short* pcm_data, short samples);
void addPCM8( unsigned char [2][1024]);
void addPCM8_512( const unsigned char [2][512]);
void getPCM(float *data, int samples, int channel, int freq, float smoothing, int derive);
void freePCM();
int getPCMnew(float *PCMdata, int channel, int freq, float smoothing, int derive,int reset);
};
#endif /** !_PCM_H */

123
3rdparty/libprojectm/PipelineMerger.cpp vendored Normal file
View File

@ -0,0 +1,123 @@
#include "PipelineMerger.hpp"
#include "RenderItemMatcher.hpp"
#include "RenderItemMergeFunction.hpp"
const double PipelineMerger::e(2.71828182845904523536);
const double PipelineMerger::s(0.5);
void PipelineMerger::mergePipelines(const Pipeline & a, const Pipeline & b, Pipeline & out, RenderItemMatcher::MatchResults & results, RenderItemMergeFunction & mergeFunction, float ratio)
{
const double x = ( ratio - 0.5 ) * 20;
const double sigmoid = 1.0 / ( 1.0 + e - s * x );
const double invratio = 1.0 - ratio;
out.textureWrap = ( ratio < 0.5 ) ? a.textureWrap : b.textureWrap;
out.screenDecay = lerp ( b.screenDecay, a.screenDecay, ratio );
out.drawables.clear();
out.compositeDrawables.clear();
for ( std::vector<RenderItem*>::const_iterator pos = a.drawables.begin();
pos != a.drawables.end(); ++pos )
{
( *pos )->masterAlpha = invratio;
out.drawables.push_back ( *pos );
}
for ( std::vector<RenderItem*>::const_iterator pos = b.drawables.begin();
pos != b.drawables.end();++pos )
{
( *pos )->masterAlpha = ratio;
out.drawables.push_back ( *pos );
}
if(ratio < 0.5)
{
const double local_ratio = (invratio - 0.5) * 2;
for (std::vector<RenderItem*>::const_iterator pos = a.compositeDrawables.begin();
pos != a.compositeDrawables.end(); ++pos)
{
(*pos)->masterAlpha = local_ratio;
out.compositeDrawables.push_back(*pos);
}
}
else
{
const double local_ratio = (ratio - 0.5) * 2;
for (std::vector<RenderItem*>::const_iterator pos = b.compositeDrawables.begin();
pos != b.compositeDrawables.end();++pos)
{
(*pos)->masterAlpha = local_ratio;
out.compositeDrawables.push_back(*pos);
}
}
/*
for (RenderItemMatchList::iterator pos = results.matches.begin(); pos != results.matches.end(); ++pos) {
RenderItem * itemA = pos->first;
RenderItem * itemB = pos->second;
RenderItem * itemC = mergeFunction(itemA, itemB, ratio);
if (itemC == 0) {
itemA->masterAlpha = ratio;
out.drawables.push_back(itemA);
itemB->masterAlpha = invratio;
out.drawables.push_back(itemB);
} else
out.drawables.push_back(itemC);
}
for (std::vector<RenderItem*>::const_iterator pos = results.unmatchedLeft.begin();
pos != results.unmatchedLeft.end(); ++pos)
{
(*pos)->masterAlpha = invratio;
out.drawables.push_back(*pos);
}
for (std::vector<RenderItem*>::const_iterator pos = results.unmatchedRight.begin();
pos != results.unmatchedRight.end(); ++pos)
{
(*pos)->masterAlpha = ratio;
out.drawables.push_back(*pos);
}
*/
if (a.staticPerPixel && b.staticPerPixel)
{
out.staticPerPixel = true;
for (int x=0;x<a.gx;x++)
{
for(int y=0;y<a.gy;y++)
{
out.x_mesh[x][y] = a.x_mesh[x][y]* invratio + b.x_mesh[x][y]*ratio;
}
}
for (int x=0;x<a.gx;x++)
{
for(int y=0;y<a.gy;y++)
{
out.y_mesh[x][y] = a.y_mesh[x][y]* invratio + b.y_mesh[x][y]*ratio;
}
}
}
if(ratio < 0.5)
{
out.compositeShader = a.compositeShader;
out.warpShader = a.warpShader;
}
else
{
out.compositeShader = b.compositeShader;
out.warpShader = b.warpShader;
}
}

28
3rdparty/libprojectm/PipelineMerger.hpp vendored Normal file
View File

@ -0,0 +1,28 @@
#ifndef PRESET_MERGE_HPP
#define PRESET_MERGE_HPP
#include "Preset.hpp"
#include "Pipeline.hpp"
#include "RenderItemMatcher.hpp"
#include "RenderItemMergeFunction.hpp"
class PipelineMerger
{
template <class T> inline static T lerp(T a, T b, float ratio)
{
return a * ratio + b * (1 - ratio);
}
public:
static void mergePipelines(const Pipeline &a, const Pipeline &b, Pipeline &out,
RenderItemMatcher::MatchResults & matching, RenderItemMergeFunction & merger, float ratio);
private :
static const double s;
static const double e;
};
#endif

23
3rdparty/libprojectm/Preset.cpp vendored Executable file
View File

@ -0,0 +1,23 @@
/*
* Preset.cpp
*
* Created on: Aug 5, 2008
* Author: struktured
*/
#include "Preset.hpp"
Preset::~Preset() {}
Preset::Preset(const std::string & presetName, const std::string & presetAuthor):
_name(presetName), _author(presetAuthor) {}
void Preset::setName(const std::string & value) { _name = value; }
const std::string & Preset::name() const { return _name; }
void Preset::setAuthor(const std::string & value) { _author = value; }
const std::string & Preset::author() const { return _author; }

38
3rdparty/libprojectm/Preset.hpp vendored Normal file
View File

@ -0,0 +1,38 @@
/*
* Preset.hpp
*
* Created on: Aug 5, 2008
* Author: carm
*/
#ifndef PRESET_HPP_
#define PRESET_HPP_
#include <string>
#include "Renderer/BeatDetect.hpp"
#include "Renderer/Pipeline.hpp"
#include "Renderer/PipelineContext.hpp"
class Preset {
public:
Preset(const std::string & name=std::string(), const std::string & author = std::string());
virtual ~Preset();
void setName(const std::string & value);
const std::string & name() const;
void setAuthor(const std::string & value);
const std::string & author() const;
virtual Pipeline & pipeline() = 0;
virtual void Render(const BeatDetect &music, const PipelineContext &context) = 0;
private:
std::string _name;
std::string _author;
};
#endif /* PRESET_HPP_ */

14
3rdparty/libprojectm/PresetChooser.cpp vendored Normal file
View File

@ -0,0 +1,14 @@
//
// C++ Implementation: PresetChooser
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "PresetChooser.hpp"

241
3rdparty/libprojectm/PresetChooser.hpp vendored Normal file
View File

@ -0,0 +1,241 @@
#ifndef PRESET_CHOOSER_HPP
#define PRESET_CHOOSER_HPP
#include "Preset.hpp"
#include "PresetLoader.hpp"
#include "RandomNumberGenerators.hpp"
#include <cassert>
#include <memory>
#include <iostream>
class PresetChooser;
/// A simple iterator class to traverse back and forth a preset directory
class PresetIterator {
public:
PresetIterator() {}
/// Instantiate a preset iterator at the given starting position
PresetIterator(std::size_t start);
/// Move iterator forward
void operator++();
/// Move iterator backword
void operator--() ;
/// Not equal comparator
bool operator !=(const PresetIterator & presetPos) const ;
/// Equality comparator
bool operator ==(const PresetIterator & presetPos) const ;
/// Returns an integer value representing the iterator position
/// @bug might become internal
/// \brief Returns the indexing value used by the current iterator.
std::size_t operator*() const;
/// Allocate a new preset given this iterator's associated preset name
/// \param presetInputs the preset inputs to associate with the preset upon construction
/// \param presetOutputs the preset outputs to associate with the preset upon construction
/// \returns an autopointer of the newly allocated preset
std::auto_ptr<Preset> allocate();
/// Set the chooser asocciated with this iterator
void setChooser(const PresetChooser & chooser);
private:
std::size_t _currentIndex;
const PresetChooser * _presetChooser;
};
/// Provides functions and iterators to select presets. Requires a preset loader upon construction
class PresetChooser {
public:
typedef PresetIterator iterator;
/// Initializes a chooser with an established preset loader.
/// \param presetLoader an initialized preset loader to choose presets from
/// \note The preset loader is refreshed via events or otherwise outside this class's scope
PresetChooser(const PresetLoader & presetLoader, bool softCutRatingsEnabled);
inline void setSoftCutRatingsEnabled(bool enabled) {
_softCutRatingsEnabled = enabled;
}
/// Choose a preset via the passed in index. Must be between 0 and num valid presets in directory
/// \param index An index lying in the interval [0, this->getNumPresets())
/// \param presetInputs the preset inputs to associate with the preset upon construction
/// \param presetOutputs the preset outputs to associate with the preset upon construction
/// \returns an auto pointer of the newly allocated preset
std::auto_ptr<Preset> directoryIndex(std::size_t index) const;
/// Gets the number of presets last believed to exist in the preset loader's filename collection
/// \returns the number of presets in the collection
std::size_t size() const;
/// An STL-esque iterator to begin traversing presets from a directory
/// \param index the index to begin iterating at. Assumed valid between [0, num presets)
/// \returns the position of the first preset in the collection
PresetIterator begin(unsigned int index) const;
/// An STL-esque iterator to begin traversing presets from a directory
/// \returns the position of the first preset in the collection
PresetIterator begin();
/// An STL-esque iterator to retrieve an end position from a directory
/// \returns the end position of the collection
PresetIterator end() const;
/// Perform a weighted sample to select a preset (uses preset rating values)
/// \returns an iterator to the randomly selected preset
iterator weightedRandom(bool hardCut) const;
/// True if no presets in directory
bool empty() const;
inline void nextPreset(PresetIterator & presetPos);
inline void previousPreset(PresetIterator & presetPos);
private:
std::vector<float> sampleWeights;
const PresetLoader * _presetLoader;
bool _softCutRatingsEnabled;
};
inline PresetChooser::PresetChooser(const PresetLoader & presetLoader, bool softCutRatingsEnabled):_presetLoader(&presetLoader), _softCutRatingsEnabled(softCutRatingsEnabled) {
}
inline std::size_t PresetChooser::size() const {
return _presetLoader->size();
}
inline void PresetIterator::setChooser(const PresetChooser & chooser) {
_presetChooser = &chooser;
}
inline std::size_t PresetIterator::operator*() const {
return _currentIndex;
}
inline PresetIterator::PresetIterator(std::size_t start):_currentIndex(start) {}
inline void PresetIterator::operator++() {
assert(_currentIndex < _presetChooser->size());
_currentIndex++;
}
inline void PresetIterator::operator--() {
assert(_currentIndex > 0);
_currentIndex--;
}
inline bool PresetIterator::operator !=(const PresetIterator & presetPos) const {
return (*presetPos != **this);
}
inline bool PresetIterator::operator ==(const PresetIterator & presetPos) const {
return (*presetPos == **this);
}
inline std::auto_ptr<Preset> PresetIterator::allocate() {
return _presetChooser->directoryIndex(_currentIndex);
}
inline void PresetChooser::nextPreset(PresetIterator & presetPos) {
if (this->empty()) {
return;
}
// Case: idle preset currently running, selected first preset of chooser
else if (presetPos == this->end())
presetPos = this->begin();
else
++(presetPos);
// Case: already at last preset, loop to beginning
if (((presetPos) == this->end())) {
presetPos = this->begin();
}
}
inline void PresetChooser::previousPreset(PresetIterator & presetPos) {
if (this->empty())
return;
// Case: idle preset currently running, selected last preset of chooser
else if (presetPos == this->end()) {
--(presetPos);
}
else if (presetPos != this->begin()) {
--(presetPos);
}
else {
presetPos = this->end();
--(presetPos);
}
}
inline PresetIterator PresetChooser::begin() {
PresetIterator pos(0);
pos.setChooser(*this);
return pos;
}
inline PresetIterator PresetChooser::begin(unsigned int index) const{
PresetIterator pos(index);
pos.setChooser(*this);
return pos;
}
inline PresetIterator PresetChooser::end() const {
PresetIterator pos(_presetLoader->size());
pos.setChooser(*this);
return pos;
}
inline bool PresetChooser::empty() const {
return _presetLoader->size() == 0;
}
inline std::auto_ptr<Preset> PresetChooser::directoryIndex(std::size_t index) const {
return _presetLoader->loadPreset(index);
}
inline PresetChooser::iterator PresetChooser::weightedRandom(bool hardCut) const {
// TODO make a sophisticated function object interface to determine why a certain rating
// category is chosen, or weighted distribution thereover.
const PresetRatingType ratingType = hardCut || (!_softCutRatingsEnabled) ?
HARD_CUT_RATING_TYPE : SOFT_CUT_RATING_TYPE;
const std::size_t ratingsTypeIndex = static_cast<std::size_t>(ratingType);
const std::vector<int> & weights = _presetLoader->getPresetRatings()[ratingsTypeIndex];
const std::size_t index = RandomNumberGenerators::weightedRandom
(weights,
_presetLoader->getPresetRatingsSums()[ratingsTypeIndex]);
return begin(index);
}
#endif

24
3rdparty/libprojectm/PresetFactory.cpp vendored Normal file
View File

@ -0,0 +1,24 @@
#include "PresetFactory.hpp"
const std::string PresetFactory::IDLE_PRESET_PROTOCOL("idle");
std::string PresetFactory::protocol(const std::string & url, std::string & path) {
#ifdef __APPLE__
// NOTE: Brian changed this from url.find_first_of to url.find, since presumably we want to find the first occurence of
// :// and not the first occurence of any colon or forward slash. At least that fixed a bug in the Mac OS X build.
std::size_t pos = url.find("://");
#else
std::size_t pos = url.find_first_of("://");
#endif
if (pos == std::string::npos)
return std::string();
else {
path = url.substr(pos + 3, url.length());
std::cout << "[PresetFactory] path is " << path << std::endl;
std::cout << "[PresetFactory] url is " << url << std::endl;
return url.substr(0, pos);
}
}

42
3rdparty/libprojectm/PresetFactory.hpp vendored Normal file
View File

@ -0,0 +1,42 @@
//
// C++ Interface: PresetFactory
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "Preset.hpp"
#include <memory>
#ifndef __PRESET_FACTORY_HPP
#define __PRESET_FACTORY_HPP
class PresetFactory {
public:
static const std::string IDLE_PRESET_PROTOCOL;
static std::string protocol(const std::string & url, std::string & path);
inline PresetFactory() {}
inline virtual ~PresetFactory() {}
/// Constructs a new preset given an url and optional meta data
/// \param url a locational identifier referencing the preset
/// \param name the preset name
/// \param author the preset author
/// \returns a valid preset object
virtual std::auto_ptr<Preset> allocate(const std::string & url, const std::string & name=std::string(),
const std::string & author=std::string()) = 0;
/// Returns a space separated list of supported extensions
virtual std::string supportedExtensions() const = 0;
};
#endif

View File

@ -0,0 +1,81 @@
//
// C++ Implementation: PresetFactoryManager
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "PresetFactoryManager.hpp"
#ifndef DISABLE_MILKDROP_PRESETS
#include "MilkdropPresetFactory/MilkdropPresetFactory.hpp"
#endif
#ifndef DISABLE_NATIVE_PRESETS
#include "NativePresetFactory/NativePresetFactory.hpp"
#endif
#include <sstream>
PresetFactoryManager::PresetFactoryManager() : _gx(0), _gy(0) {}
PresetFactoryManager::~PresetFactoryManager() {
for (std::vector<PresetFactory *>::iterator pos = _factoryList.begin();
pos != _factoryList.end(); ++pos) {
assert(*pos);
delete(*pos);
}
}
void PresetFactoryManager::initialize(int gx, int gy) {
_gx = gx;
_gy = gy;
PresetFactory * factory;
#ifndef DISABLE_MILKDROP_PRESETS
factory = new MilkdropPresetFactory(_gx, _gy);
registerFactory(factory->supportedExtensions(), factory);
#endif
#ifndef DISABLE_NATIVE_PRESETS
factory = new NativePresetFactory();
registerFactory(factory->supportedExtensions(), factory);
#endif
}
// Current behavior if a conflict is occurs is to override the previous request
void PresetFactoryManager::registerFactory(const std::string & extensions, PresetFactory * factory) {
std::stringstream ss(extensions);
std::string extension;
_factoryList.push_back(factory);
while (ss >> extension) {
if (_factoryMap.count(extension)) {
std::cerr << "[PresetFactoryManager] Warning: extension \"" << extension <<
"\" already has a factory. New factory handler ignored." << std::endl;
} else {
_factoryMap.insert(std::make_pair(extension, factory));
}
}
}
PresetFactory & PresetFactoryManager::factory(const std::string & extension) {
if (!_factoryMap.count(extension)) {
std::ostringstream os;
os << "No factory associated with \"" << extension << "\"." << std::endl;
throw PresetFactoryException(os.str());
}
return *_factoryMap[extension];
}
bool PresetFactoryManager::extensionHandled(const std::string & extension) const {
return _factoryMap.count(extension);
}

View File

@ -0,0 +1,59 @@
//
// C++ Implementation: PresetFactoryManager
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef __PRESET_FACTORY_MANAGER_HPP
#define __PRESET_FACTORY_MANAGER_HPP
#include "PresetFactory.hpp"
/// A simple exception class to strongly type all preset factory related issues
class PresetFactoryException : public std::exception
{
public:
inline PresetFactoryException(const std::string & message) : _message(message) {}
virtual ~PresetFactoryException() throw() {}
const std::string & message() const { return _message; }
private:
std::string _message;
};
/// A manager of preset factories
class PresetFactoryManager {
public:
PresetFactoryManager();
~PresetFactoryManager();
/// Initializes the manager with mesh sizes specified
/// \param gx the width of the mesh
/// \param gy the height of the mesh
/// \note This must be called once before any other methods
void initialize(int gx, int gy);
/// Requests a factory given a preset extension type
/// \param extension a string denoting the preset suffix type
/// \throws PresetFactoryException if the extension is unhandled
/// \returns a valid preset factory associated with the extension
PresetFactory & factory(const std::string & extension);
/// Tests if an extension has been registered with a factory
/// \param extension the file name extension to verify
/// \returns true if a factory exists, false otherwise
bool extensionHandled(const std::string & extension) const;
private:
int _gx, _gy;
mutable std::map<std::string, PresetFactory *> _factoryMap;
mutable std::vector<PresetFactory *> _factoryList;
void registerFactory(const std::string & extension, PresetFactory * factory);
};
#endif

281
3rdparty/libprojectm/PresetLoader.cpp vendored Normal file
View File

@ -0,0 +1,281 @@
//
// C++ Implementation: PresetLoader
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "PresetLoader.hpp"
#include "Preset.hpp"
#include "PresetFactory.hpp"
#include <iostream>
#include <sstream>
#include <set>
#ifdef LINUX
extern "C"
{
#include <errno.h>
}
#endif
#ifdef MACOS
extern "C"
{
#include <errno.h>
}
#endif
#include <cassert>
#include "fatal.h"
#include "Common.hpp"
PresetLoader::PresetLoader (int gx, int gy, std::string dirname = std::string()) :_dirname ( dirname ), _dir ( 0 )
{
_presetFactoryManager.initialize(gx,gy);
// Do one scan
if ( _dirname != std::string() )
rescan();
else
clear();
}
PresetLoader::~PresetLoader()
{
if ( _dir )
closedir ( _dir );
}
void PresetLoader::setScanDirectory ( std::string dirname )
{
_dirname = dirname;
}
void PresetLoader::rescan()
{
// std::cerr << "Rescanning..." << std::endl;
// Clear the directory entry collection
clear();
// If directory already opened, close it first
if ( _dir )
{
closedir ( _dir );
_dir = 0;
}
// Allocate a new a stream given the current directory name
if ( ( _dir = opendir ( _dirname.c_str() ) ) == NULL )
{
handleDirectoryError();
return; // no files loaded. _entries is empty
}
struct dirent * dir_entry;
std::set<std::string> alphaSortedFileSet;
std::set<std::string> alphaSortedPresetNameSet;
while ( ( dir_entry = readdir ( _dir ) ) != NULL )
{
std::ostringstream out;
// Convert char * to friendly string
std::string filename ( dir_entry->d_name );
// Verify extension is projectm or milkdrop
if (!_presetFactoryManager.extensionHandled(parseExtension(filename)))
continue;
if ( filename.length() > 0 && filename[0] == '.' )
continue;
// Create full path name
out << _dirname << PATH_SEPARATOR << filename;
// Add to our directory entry collection
alphaSortedFileSet.insert ( out.str() );
alphaSortedPresetNameSet.insert ( filename );
// the directory entry struct is freed elsewhere
}
// Push all entries in order from the file set to the file entries member (which is an indexed vector)
for ( std::set<std::string>::iterator pos = alphaSortedFileSet.begin();
pos != alphaSortedFileSet.end();++pos )
_entries.push_back ( *pos );
// Push all preset names in similar fashion
for ( std::set<std::string>::iterator pos = alphaSortedPresetNameSet.begin();
pos != alphaSortedPresetNameSet.end();++pos )
_presetNames.push_back ( *pos );
// Give all presets equal rating of 3 - why 3? I don't know
_ratings = std::vector<RatingList>(TOTAL_RATING_TYPES, RatingList( _presetNames.size(), 3 ));
_ratingsSums = std::vector<int>(TOTAL_RATING_TYPES, 3 * _presetNames.size());
assert ( _entries.size() == _presetNames.size() );
}
std::auto_ptr<Preset> PresetLoader::loadPreset ( unsigned int index ) const
{
// Check that index isn't insane
assert ( index >= 0 );
assert ( index < _entries.size() );
// Return a new autopointer to a preset
const std::string extension = parseExtension ( _entries[index] );
return _presetFactoryManager.factory(extension).allocate
( _entries[index], _presetNames[index] );
}
std::auto_ptr<Preset> PresetLoader::loadPreset ( const std::string & url ) const
{
// Return a new autopointer to a preset
const std::string extension = parseExtension ( url );
/// @bug probably should not use url for preset name
return _presetFactoryManager.factory(extension).allocate
(url, url);
}
void PresetLoader::handleDirectoryError()
{
#ifdef WIN32
std::cerr << "[PresetLoader] warning: errno unsupported on win32 platforms. fix me" << std::endl;
#else
switch ( errno )
{
case ENOENT:
std::cerr << "[PresetLoader] ENOENT error. The path \"" << this->_dirname << "\" probably does not exist. \"man open\" for more info." << std::endl;
break;
case ENOMEM:
std::cerr << "[PresetLoader] out of memory! Are you running Windows?" << std::endl;
abort();
case ENOTDIR:
std::cerr << "[PresetLoader] directory specified is not a preset directory! Trying to continue..." << std::endl;
break;
case ENFILE:
std::cerr << "[PresetLoader] Your system has reached its open file limit. Trying to continue..." << std::endl;
break;
case EMFILE:
std::cerr << "[PresetLoader] too many files in use by projectM! Bailing!" << std::endl;
break;
case EACCES:
std::cerr << "[PresetLoader] permissions issue reading the specified preset directory." << std::endl;
break;
default:
break;
}
#endif
}
void PresetLoader::setRating(unsigned int index, int rating, const PresetRatingType ratingType)
{
assert ( index >=0 );
const unsigned int ratingTypeIndex = static_cast<unsigned int>(ratingType);
assert (index < _ratings[ratingTypeIndex].size());
_ratingsSums[ratingTypeIndex] -= _ratings[ratingTypeIndex][index];
_ratings[ratingTypeIndex][index] = rating;
_ratingsSums[ratingType] += rating;
}
unsigned int PresetLoader::addPresetURL ( const std::string & url, const std::string & presetName, const std::vector<int> & ratings)
{
_entries.push_back(url);
_presetNames.push_back ( presetName );
assert(ratings.size() == TOTAL_RATING_TYPES);
assert(ratings.size() == _ratings.size());
for (int i = 0; i < _ratings.size(); i++)
_ratings[i].push_back(ratings[i]);
for (int i = 0; i < ratings.size(); i++)
_ratingsSums[i] += ratings[i];
return _entries.size()-1;
}
void PresetLoader::removePreset ( unsigned int index )
{
_entries.erase ( _entries.begin() + index );
_presetNames.erase ( _presetNames.begin() + index );
for (int i = 0; i < _ratingsSums.size(); i++) {
_ratingsSums[i] -= _ratings[i][index];
_ratings[i].erase ( _ratings[i].begin() + index );
}
}
const std::string & PresetLoader::getPresetURL ( unsigned int index ) const
{
return _entries[index];
}
const std::string & PresetLoader::getPresetName ( unsigned int index ) const
{
return _presetNames[index];
}
int PresetLoader::getPresetRating ( unsigned int index, const PresetRatingType ratingType ) const
{
return _ratings[ratingType][index];
}
const std::vector<RatingList> & PresetLoader::getPresetRatings () const
{
return _ratings;
}
const std::vector<int> & PresetLoader::getPresetRatingsSums() const {
return _ratingsSums;
}
void PresetLoader::setPresetName(unsigned int index, std::string name) {
_presetNames[index] = name;
}
void PresetLoader::insertPresetURL ( unsigned int index, const std::string & url, const std::string & presetName, const RatingList & ratings)
{
_entries.insert ( _entries.begin() + index, url );
_presetNames.insert ( _presetNames.begin() + index, presetName );
for (int i = 0; i < _ratingsSums.size();i++) {
_ratingsSums[i] += _ratings[i][index];
_ratings[i].insert ( _ratings[i].begin() + index, ratings[i] );
}
assert ( _entries.size() == _presetNames.size() );
}

118
3rdparty/libprojectm/PresetLoader.hpp vendored Normal file
View File

@ -0,0 +1,118 @@
#ifndef __PRESET_LOADER_HPP
#define __PRESET_LOADER_HPP
#include <string> // used for path / filename stuff
#include <memory> // for auto pointers
#include <sys/types.h>
#ifdef WIN32
#include "win32-dirent.h"
#endif
#ifdef LINUX
#include <dirent.h>
#endif
#ifdef MACOS
#include <dirent.h>
#endif
#include <vector>
#include <map>
#include "PresetFactoryManager.hpp"
class Preset;
class PresetFactory;
class PresetLoader {
public:
/// Initializes the preset loader with the target directory specified
PresetLoader(int gx, int gy, std::string dirname);
~PresetLoader();
/// Load a preset by specifying it's unique identifier given when the preset url
/// was added to this loader
std::auto_ptr<Preset> loadPreset(unsigned int index) const;
std::auto_ptr<Preset> loadPreset ( const std::string & url ) const;
/// Add a preset to the loader's collection.
/// \param url an url referencing the preset
/// \param presetName a name for the preset
/// \param rating an integer representing the goodness of the preset
/// \returns The unique index assigned to the preset in the collection. Used with loadPreset
unsigned int addPresetURL ( const std::string & url, const std::string & presetName, const RatingList & ratings);
/// Add a preset to the loader's collection.
/// \param index insertion index
/// \param url an url referencing the preset
/// \param presetName a name for the preset
/// \param rating an integer representing the goodness of the preset
void insertPresetURL (unsigned int index, const std::string & url, const std::string & presetName, const RatingList & ratings);
/// Clears all presets from the collection
inline void clear() {
_entries.clear(); _presetNames.clear();
_ratings = std::vector<RatingList>(TOTAL_RATING_TYPES, RatingList());
clearRatingsSum();
}
inline void clearRatingsSum() {
_ratingsSums = std::vector<int>(TOTAL_RATING_TYPES, 0);
}
const std::vector<RatingList> & getPresetRatings() const;
const std::vector<int> & getPresetRatingsSums() const;
/// Removes a preset from the loader
/// \param index the unique identifier of the preset url to be removed
void removePreset(unsigned int index);
/// Sets the rating of a preset to a new value
void setRating(unsigned int index, int rating, const PresetRatingType ratingType);
/// Get a preset rating given an index
int getPresetRating ( unsigned int index, const PresetRatingType ratingType) const;
/// Get a preset url given an index
const std::string & getPresetURL ( unsigned int index) const;
/// Get a preset name given an index
const std::string & getPresetName ( unsigned int index) const;
/// Returns the number of presets in the active directory
inline std::size_t size() const {
return _entries.size();
}
/// Sets the directory where the loader will search for files
void setScanDirectory(std::string pathname);
/// Returns the directory path associated with this preset chooser
inline const std::string & directoryName() const {
return _dirname;
}
/// Rescans the active preset directory
void rescan();
void setPresetName(unsigned int index, std::string name);
private:
void handleDirectoryError();
std::string _dirname;
DIR * _dir;
std::vector<int> _ratingsSums;
mutable PresetFactoryManager _presetFactoryManager;
// vector chosen for speed, but not great for reverse index lookups
std::vector<std::string> _entries;
std::vector<std::string> _presetNames;
// Indexed by ratingType, preset position.
std::vector<RatingList> _ratings;
};
#endif

View File

@ -0,0 +1,122 @@
#ifndef RANDOM_NUMBER_GENERATORS_HPP
#define RANDOM_NUMBER_GENERATORS_HPP
#include <cmath>
#include <vector>
#include <cassert>
#include <iostream>
#define WEIGHTED_RANDOM_DEBUG 0
namespace RandomNumberGenerators {
inline float uniform()
/* Uniform random number generator x(n+1)= a*x(n) mod c
with a = pow(7,5) and c = pow(2,31)-1.
Copyright (c) Tao Pang 1997. */
{
const int ia=16807,ic=2147483647,iq=127773,ir=2836;
int il,ih,it;
float rc;
static int iseed = rand();
ih = iseed/iq;
il = iseed%iq;
it = ia*il-ir*ih;
if (it > 0)
{
iseed = it;
}
else
{
iseed = ic+it;
}
rc = ic;
return iseed/rc;
}
inline float gaussian(float mean, float sigma)
{
float x1, x2, w, y1, y2;
do {
x1 = 2.0 * uniform() - 1.0;
x2 = 2.0 * uniform() - 1.0;
w = x1 * x1 + x2 * x2;
} while ( w >= 1.0 );
w = sqrt( (-2.0 * log( w ) ) / w );
y1 = x1 * w;
y2 = x2 * w;
float ret = y1*sigma + mean;
return ret;
}
inline std::size_t uniformInteger(std::size_t upperBound=1) {
/// @bug there was a man entry about how this leads to a lousy uniform
/// @bug distribution in practice. should probably review
assert(upperBound > 0);
return ((rand()) % ((int)upperBound));
}
/// Randomizes from probabilistically weighted distribution. Thus,
/// sum of passed in weights should be 1.0
inline std::size_t weightedRandomNormalized(std::vector<float> weights) {
// Choose a random bounded mass between 0 and 1
float cutoff = ((float)(rand())) / (float)RAND_MAX;
//std::cout << "cutoff : " << cutoff << std::endl;
// Sum up mass, stopping when cutoff is reached. This is the typical
// weighted sampling algorithm.
float mass = 0;
for (std::size_t i = 0; i< weights.size() ; i++) {
mass += weights[i];
//std::cout << "mass: " << mass << std::endl;
if (mass >= cutoff)
return i;
}
// Just in case something slips through the cracks
return weights.size()-1;
}
inline std::size_t weightedRandom(const std::vector<int> & weights, unsigned int weightTotalHint = 0) {
if (weightTotalHint == 0) {
for (std::size_t i = 0; i < weights.size();i++)
weightTotalHint += weights[i];
}
const int sampledSum = uniformInteger(weightTotalHint);
int sum = 0;
if (WEIGHTED_RANDOM_DEBUG) std::cout << "[RNG::weightedRandom()] weightTotal = " << weightTotalHint <<
std::endl;
for (std::size_t i = 0; i < weights.size();i++) {
if (WEIGHTED_RANDOM_DEBUG)
std::cout << "[RNG::weightedRandom()] weight[" << i << "] = " << weights[i] <<
std::endl;
sum += weights[i];
if (sampledSum <= sum) {
if (WEIGHTED_RANDOM_DEBUG)
std::cout << "[RNG::weightedRandom()] sampled index " << i << "(" <<
"running sum = " << sum << ", sampled sum = " << sampledSum << std::endl;
return i;
}
}
return weights.size()-1;
}
}
#endif

186
3rdparty/libprojectm/Renderer/BeatDetect.cpp vendored Executable file
View File

@ -0,0 +1,186 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* Takes sound data from wherever and returns beat detection values
* Uses statistical Energy-Based methods. Very simple
*
* Some stuff was taken from Frederic Patin's beat-detection article,
* you'll find it online
*/
#include <stdlib.h>
#include <stdio.h>
#include "wipemalloc.h"
#include "Common.hpp"
#include "PCM.hpp"
#include <cmath>
#include "BeatDetect.hpp"
BeatDetect::BeatDetect(PCM *pcm) {
int x,y;
this->pcm=pcm;
this->vol_instant=0;
this->vol_history=0;
for (y=0;y<80;y++)
{
this->vol_buffer[y]=0;
}
this->beat_buffer_pos=0;
for (x=0;x<32;x++) {
this->beat_instant[x]=0;
this->beat_history[x]=0;
this->beat_val[x]=1.0;
this->beat_att[x]=1.0;
this->beat_variance[x]=0;
for (y=0;y<80;y++) {
this->beat_buffer[x][y]=0;
}
}
this->treb = 0;
this->mid = 0;
this->bass = 0;
this->vol_old = 0;
this->beat_sensitivity = 10.00;
this->treb_att = 0;
this->mid_att = 0;
this->bass_att = 0;
this->vol = 0;
}
BeatDetect::~BeatDetect()
{
}
void BeatDetect::reset() {
this->treb = 0;
this->mid = 0;
this->bass = 0;
this->treb_att = 0;
this->mid_att = 0;
this->bass_att = 0;
}
void BeatDetect::detectFromSamples() {
vol_old = vol;
bass=0;mid=0;treb=0;
getBeatVals(pcm->pcmdataL,pcm->pcmdataR);
}
void BeatDetect::getBeatVals( float *vdataL,float *vdataR ) {
int linear=0;
int x,y;
float temp2=0;
vol_instant=0;
for ( x=0;x<16;x++)
{
beat_instant[x]=0;
for ( y=linear*2;y<(linear+8+x)*2;y++)
{
beat_instant[x]+=((vdataL[y]*vdataL[y])+(vdataR[y]*vdataR[y]))*(1.0/(8+x));
// printf( "beat_instant[%d]: %f %f %f\n", x, beat_instant[x], vdataL[y], vdataR[y] );
vol_instant+=((vdataL[y]*vdataL[y])+(vdataR[y]*vdataR[y]))*(1.0/512.0);
}
//printf("1");
linear=y/2;
beat_history[x]-=(beat_buffer[x][beat_buffer_pos])*.0125;
beat_buffer[x][beat_buffer_pos]=beat_instant[x];
beat_history[x]+=(beat_instant[x])*.0125;
beat_val[x]=(beat_instant[x])/(beat_history[x]);
beat_att[x]+=(beat_instant[x])/(beat_history[x]);
//printf("2\n");
}
//printf("b\n");
vol_history-=(vol_buffer[beat_buffer_pos])*.0125;
vol_buffer[beat_buffer_pos]=vol_instant;
vol_history+=(vol_instant)*.0125;
mid=0;
for(x=1;x<10;x++)
{
mid+=(beat_instant[x]);
temp2+=(beat_history[x]);
}
mid=mid/(1.5*temp2);
temp2=0;
treb=0;
for(x=10;x<16;x++)
{
treb+=(beat_instant[x]);
temp2+=(beat_history[x]);
}
//printf("c\n");
treb=treb/(1.5*temp2);
// *vol=vol_instant/(1.5*vol_history);
vol=vol_instant/(1.5*vol_history);
bass=(beat_instant[0])/(1.5*beat_history[0]);
if ( projectM_isnan( treb ) ) {
treb = 0.0;
}
if ( projectM_isnan( mid ) ) {
mid = 0.0;
}
if ( projectM_isnan( bass ) ) {
bass = 0.0;
}
treb_att=.6 * treb_att + .4 * treb;
mid_att=.6 * mid_att + .4 * mid;
bass_att=.6 * bass_att + .4 * bass;
if(bass_att>100)bass_att=100;
if(bass >100)bass=100;
if(mid_att>100)mid_att=100;
if(mid >100)mid=100;
if(treb_att>100)treb_att=100;
if(treb >100)treb=100;
if(vol>100)vol=100;
// *vol=(beat_instant[3])/(beat_history[3]);
beat_buffer_pos++;
if( beat_buffer_pos>79)beat_buffer_pos=0;
}

74
3rdparty/libprojectm/Renderer/BeatDetect.hpp vendored Executable file
View File

@ -0,0 +1,74 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Beat detection class. Takes decompressed sound buffers and returns
* various characteristics
*
* $Log$
*
*/
#ifndef _BEAT_DETECT_H
#define _BEAT_DETECT_H
#include "../PCM.hpp"
#include "../dlldefs.h"
class DLLEXPORT BeatDetect
{
public:
float treb ;
float mid ;
float bass ;
float vol_old ;
float beat_sensitivity;
float treb_att ;
float mid_att ;
float bass_att ;
float vol;
PCM *pcm;
/** Methods */
BeatDetect(PCM *pcm);
~BeatDetect();
void initBeatDetect();
void reset();
void detectFromSamples();
void getBeatVals ( float *vdataL, float *vdataR );
private:
/** Vars */
float beat_buffer[32][80],
beat_instant[32],
beat_history[32];
float beat_val[32],
beat_att[32],
beat_variance[32];
int beat_buffer_pos;
float vol_buffer[80],
vol_instant,
vol_history;
};
#endif /** !_BEAT_DETECT_H */

View File

@ -0,0 +1,28 @@
PROJECT(Renderer)
cmake_minimum_required(VERSION 2.4.0)
if(COMMAND cmake_policy)
cmake_policy(SET CMP0003 NEW)
endif(COMMAND cmake_policy)
SET(SOIL_SOURCES SOIL/image_DXT.c SOIL/image_helper.c SOIL/SOIL.c SOIL/stb_image_aug.c)
SET(Renderer_SOURCES FBO.cpp MilkdropWaveform.cpp PerPixelMesh.cpp Pipeline.cpp Renderer.cpp ShaderEngine.cpp UserTexture.cpp Waveform.cpp
Filters.cpp PerlinNoise.cpp PipelineContext.cpp Renderable.cpp BeatDetect.cpp Shader.cpp TextureManager.cpp VideoEcho.cpp
RenderItemDistanceMetric.cpp RenderItemMatcher.cpp ${SOIL_SOURCES})
IF(NOT MSVC)
SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
ENDIF(NOT MSVC)
if(MSVC)
SET (MATH_LIBRARIES )
else(MSVC)
SET (MATH_LIBRARIES m)
endif(MSVC)
INCLUDE_DIRECTORIES(${projectM_SOURCE_DIR})
ADD_LIBRARY(Renderer STATIC ${Renderer_SOURCES})
SET_TARGET_PROPERTIES(Renderer PROPERTIES VERSION 2.00 SOVERSION 2)
TARGET_LINK_LIBRARIES(Renderer ${MATH_LIBRARIES} projectM)

293
3rdparty/libprojectm/Renderer/FBO.cpp vendored Executable file
View File

@ -0,0 +1,293 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2004 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id: FBO.c,v 1.1.1.1 2005/12/23 18:05:00 psperl Exp $
*
* Render this methods
*/
#include <stdio.h>
//#include <GL/gl.h>
#include <iostream>
#include "Common.hpp"
#include "FBO.hpp"
RenderTarget::~RenderTarget() {
glDeleteTextures( 1, &this->textureID[0]);
#ifdef USE_FBO
if (useFBO)
{
glDeleteTextures( 1, &this->textureID[1] );
glDeleteRenderbuffersEXT(1, &this->depthb[0]);
glDeleteFramebuffersEXT(1, &this->fbuffer[0]);
if(renderToTexture)
{
glDeleteTextures( 1, &this->textureID[2] );
glDeleteRenderbuffersEXT(1, &this->depthb[1]);
glDeleteFramebuffersEXT(1, &this->fbuffer[1]);
}
}
#endif
}
GLuint RenderTarget::initRenderToTexture()
{
#ifdef USE_FBO
if (this->useFBO==1)
{
this->renderToTexture=1;
GLuint fb2, depth_rb2;
glGenFramebuffersEXT(1, &fb2);
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fb2 );
glGenRenderbuffersEXT(1, &depth_rb2);
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, depth_rb2 );
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, this->texsize,this->texsize );
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb2 );
this->fbuffer[1] = fb2;
this->depthb[1]= depth_rb2;
glGenTextures(1, &this->textureID[2]);
glBindTexture(GL_TEXTURE_2D, this->textureID[2]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, this->textureID[2], 0 );
return this->textureID[2];
}
#endif
return -1;
}
/** Creates new pbuffers */
RenderTarget::RenderTarget(int texsize, int width, int height) : useFBO(false) {
int mindim = 0;
int origtexsize = 0;
this->renderToTexture = 0;
this->texsize = texsize;
#ifdef USE_FBO
glewInit();
// Forceably disable FBO if user requested it but the video card / driver lacks
// the appropraite frame buffer extension.
if (useFBO = glewIsSupported("GL_EXT_framebuffer_object"))
{
GLuint fb, depth_rb, rgba_tex, other_tex;
glGenFramebuffersEXT(1, &fb);
glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fb );
glGenRenderbuffersEXT(1, &depth_rb);
glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, depth_rb );
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, this->texsize,this->texsize );
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb );
this->fbuffer[0] = fb;
this->depthb[0]= depth_rb;
glGenTextures(1, &other_tex);
glBindTexture(GL_TEXTURE_2D,other_tex);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glGenerateMipmapEXT(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glGenTextures(1, &rgba_tex);
glBindTexture(GL_TEXTURE_2D, rgba_tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, texsize, texsize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//glGenerateMipmapEXT(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, rgba_tex, 0 );
this->textureID[0] = rgba_tex;
this->textureID[1] = other_tex;
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status == GL_FRAMEBUFFER_COMPLETE_EXT) {
return;
}
std::cerr << "[projecM] warning: FBO support not detected. Using fallback." << std::endl;
}
#endif
// Can reach here via two code paths:
// (1) useFBO was set to false externally by cmake / system setting / etc.
// (2) useFBO was true but forced to false as it failed to pass all the GLU extension checks.
/** Fallback pbuffer creation via teximage hack */
/** Check the texture size against the viewport size */
/** If the viewport is smaller, then we'll need to scale the texture size down */
/** If the viewport is larger, scale it up */
mindim = width < height ? width : height;
origtexsize = this->texsize;
this->texsize = nearestPower2( mindim, SCALE_MINIFY );
glGenTextures(1, &this->textureID[0] );
glBindTexture(GL_TEXTURE_2D, this->textureID[0] );
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
this->texsize, this->texsize,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
NULL);
return;
}
void RenderTarget::fallbackRescale(int width, int height)
{
int mindim = width < height ? width : height;
int origtexsize = this->texsize;
this->texsize = nearestPower2( mindim, SCALE_MINIFY );
/* Create the texture that will be bound to the render this */
/*
if ( this->texsize != origtexsize ) {
glDeleteTextures( 1, &this->textureID[0] );
}
*/
glGenTextures(1, &this->textureID[0] );
glBindTexture(GL_TEXTURE_2D, this->textureID[0] );
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
this->texsize, this->texsize,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
NULL);
}
/** Destroys the pbuffer */
/** Locks the pbuffer */
void RenderTarget::lock() {
#ifdef USE_FBO
if(this->useFBO)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fbuffer[0]);
}
#endif
}
/** Unlocks the pbuffer */
void RenderTarget::unlock() {
#ifdef USE_FBO
if(this->useFBO)
{
glBindTexture( GL_TEXTURE_2D, this->textureID[1] );
glCopyTexSubImage2D( GL_TEXTURE_2D,
0, 0, 0, 0, 0,
this->texsize, this->texsize );
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
return;
}
#endif
/** Fallback texture path */
glBindTexture( GL_TEXTURE_2D, this->textureID[0] );
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, this->texsize, this->texsize );
}
/**
* Calculates the nearest power of two to the given number using the
* appropriate rule
*/
int RenderTarget::nearestPower2( int value, TextureScale scaleRule ) {
int x = value;
int power = 0;
while ( ( x & 0x01 ) != 1 ) {
x >>= 1;
}
if ( x == 1 ) {
return value;
} else {
x = value;
while ( x != 0 ) {
x >>= 1;
power++;
}
switch ( scaleRule ) {
case SCALE_NEAREST:
if ( ( ( 1 << power ) - value ) <= ( value - ( 1 << ( power - 1 ) ) ) ) {
return 1 << power;
} else {
return 1 << ( power - 1 );
}
case SCALE_MAGNIFY:
return 1 << power;
case SCALE_MINIFY:
return 1 << ( power - 1 );
default:
break;
}
}
return 0;
}

96
3rdparty/libprojectm/Renderer/FBO.hpp vendored Executable file
View File

@ -0,0 +1,96 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id: FBO.hpp,v 1.1.1.1 2005/12/23 18:05:00 psperl Exp $
*
* Opaque render target
*
*/
#ifndef _RENDERTARGET_H
#define _RENDERTARGET_H
#ifdef USE_FBO
#ifdef USE_NATIVE_GLEW
#include "glew.h"
#else
#include <GL/glew.h>
#endif
#endif
#ifdef MACOS
#include <OpenGL/gl.h>
#include <AGL/agl.h>
#endif /** MACOS */
#ifdef WIN32
#include <windows.h>
#endif /** WIN32 */
#ifdef LINUX
#ifdef USE_GLES1
#include <GLES/gl.h>
#else
#include <GL/gl.h>
#include <GL/glx.h>
#endif
#endif
typedef enum { SCALE_NEAREST, SCALE_MAGNIFY, SCALE_MINIFY } TextureScale;
class RenderTarget {
public:
/** Texture size */
int texsize;
int useFBO;
int renderToTexture;
~RenderTarget();
RenderTarget( int texsize, int width, int height );
void lock();
void unlock();
GLuint initRenderToTexture();
int nearestPower2( int value, TextureScale scaleRule );
void fallbackRescale(int width, int height);
/** Opaque pbuffer context and pbuffer */
/*
#ifdef MACOS
void *origContext;
void *pbufferContext;
void *pbuffer;
#endif
*/
/** Render target texture ID for non-pbuffer systems */
GLuint textureID[3];
#ifdef USE_FBO
GLuint fbuffer[2];
GLuint depthb[2];
#endif
};
#endif /** !_RENDERTARGET_H */

View File

@ -0,0 +1,98 @@
/*
* Filters.cpp
*
* Created on: Jun 18, 2008
* Author: pete
*/
#include "Common.hpp"
#ifdef USE_GLES1
#include <GLES/gl.h>
#else
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#endif
#include "Filters.hpp"
void Brighten::Draw(RenderContext &context)
{
float points[4][2] = {{-0.5, -0.5},
{-0.5, 0.5},
{ 0.5, 0.5},
{ 0.5, -0.5}};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2,GL_FLOAT,0,points);
glColor4f(1.0, 1.0, 1.0, 1.0);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
glBlendFunc(GL_ZERO, GL_DST_COLOR);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_VERTEX_ARRAY);
}
void Darken::Draw(RenderContext &context)
{
float points[4][2] = {{-0.5, -0.5},
{-0.5, 0.5},
{ 0.5, 0.5},
{ 0.5, -0.5}};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2,GL_FLOAT,0,points);
glColor4f(1.0, 1.0, 1.0, 1.0);
glBlendFunc(GL_ZERO, GL_DST_COLOR);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_VERTEX_ARRAY);
}
void Invert::Draw(RenderContext &context)
{
float points[4][2] = {{-0.5, -0.5},
{-0.5, 0.5},
{ 0.5, 0.5},
{ 0.5, -0.5}};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2,GL_FLOAT,0,points);
glColor4f(1.0, 1.0, 1.0, 1.0);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_VERTEX_ARRAY);
}
void Solarize::Draw(RenderContext &context)
{
float points[4][2] = {{-0.5, -0.5},
{-0.5, 0.5},
{ 0.5, 0.5},
{ 0.5, -0.5}};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2,GL_FLOAT,0,points);
glColor4f(1.0, 1.0, 1.0, 1.0);
glBlendFunc(GL_ZERO, GL_ONE_MINUS_DST_COLOR);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
glBlendFunc(GL_DST_COLOR, GL_ONE);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_VERTEX_ARRAY);
}

View File

@ -0,0 +1,41 @@
/*
* Filters.hpp
*
* Created on: Jun 18, 2008
* Author: pete
*/
#ifndef FILTERS_HPP_
#define FILTERS_HPP_
#include "Renderable.hpp"
class Brighten : public RenderItem
{
public:
Brighten(){}
void Draw(RenderContext &context);
};
class Darken : public RenderItem
{
public:
Darken(){}
void Draw(RenderContext &context);
};
class Invert : public RenderItem
{
public:
Invert(){}
void Draw(RenderContext &context);
};
class Solarize : public RenderItem
{
public:
Solarize(){}
void Draw(RenderContext &context);
};
#endif /* FILTERS_HPP_ */

View File

@ -0,0 +1,370 @@
/*
* MilkdropWaveform.cpp
*
* Created on: Jun 25, 2008
* Author: pete
*/
#include <iostream>
#ifdef LINUX
#include <GL/gl.h>
#endif
#ifdef WIN32
#include "glew.h"
#endif
#ifdef __APPLE__
#include <GL/gl.h>
#endif
#include "MilkdropWaveform.hpp"
#include "math.h"
#include "BeatDetect.hpp"
MilkdropWaveform::MilkdropWaveform(): RenderItem(),
x(0.5), y(0.5), r(1), g(0), b(0), a(1), mystery(0), mode(Line), scale(10), smoothing(0), rot(0), samples(0),modOpacityStart(0),modOpacityEnd(1),
modulateAlphaByVolume(false), maximizeColors(false), additive(false), dots(false), thick(false), loop(false) {}
void MilkdropWaveform::Draw(RenderContext &context)
{
WaveformMath(context);
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glLoadIdentity();
if(modulateAlphaByVolume) ModulateOpacityByVolume(context);
else temp_a = a;
MaximizeColors(context);
#ifndef USE_GLES1
if(dots==1) glEnable(GL_LINE_STIPPLE);
#endif
//Thick wave drawing
if (thick==1) glLineWidth( (context.texsize < 512 ) ? 2 : 2*context.texsize/512);
else glLineWidth( (context.texsize < 512 ) ? 1 : context.texsize/512);
//Additive wave drawing (vice overwrite)
if (additive==1)glBlendFunc(GL_SRC_ALPHA, GL_ONE);
else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTranslatef(.5, .5, 0);
glRotatef(rot, 0, 0, 1);
glScalef(aspectScale, 1.0, 1.0);
glTranslatef(-.5, -.5, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(2,GL_FLOAT,0,wavearray);
if (loop)
glDrawArrays(GL_LINE_LOOP,0,samples);
else
glDrawArrays(GL_LINE_STRIP,0,samples);
if (two_waves)
{
glVertexPointer(2,GL_FLOAT,0,wavearray2);
if (loop)
glDrawArrays(GL_LINE_LOOP,0,samples);
else
glDrawArrays(GL_LINE_STRIP,0,samples);
}
#ifndef USE_GLES1
if(dots==1) glDisable(GL_LINE_STIPPLE);
#endif
glPopMatrix();
}
void MilkdropWaveform::ModulateOpacityByVolume(RenderContext &context)
{
//modulate volume by opacity
//
//set an upper and lower bound and linearly
//calculate the opacity from 0=lower to 1=upper
//based on current volume
if (context.beatDetect->vol<= modOpacityStart) temp_a=0.0;
else if (context.beatDetect->vol>=modOpacityEnd) temp_a=a;
else temp_a=a*((context.beatDetect->vol-modOpacityStart)/(modOpacityEnd-modOpacityStart));
}
void MilkdropWaveform::MaximizeColors(RenderContext &context)
{
float wave_r_switch=0, wave_g_switch=0, wave_b_switch=0;
//wave color brightening
//
//forces max color value to 1.0 and scales
// the rest accordingly
if(mode==Blob2 || mode==Blob5)
switch(context.texsize)
{
case 256: temp_a *= 0.07f; break;
case 512: temp_a *= 0.09f; break;
case 1024: temp_a *= 0.11f; break;
case 2048: temp_a *= 0.13f; break;
}
else if(mode==Blob3)
{
switch(context.texsize)
{
case 256: temp_a *= 0.075f; break;
case 512: temp_a *= 0.15f; break;
case 1024: temp_a *= 0.22f; break;
case 2048: temp_a *= 0.33f; break;
}
temp_a*=1.3f;
temp_a*=powf(context.beatDetect->treb , 2.0f);
}
if (maximizeColors==true)
{
if(r>=g && r>=b) //red brightest
{
wave_b_switch=b*(1/r);
wave_g_switch=g*(1/r);
wave_r_switch=1.0;
}
else if (b>=g && b>=r) //blue brightest
{
wave_r_switch=r*(1/b);
wave_g_switch=g*(1/b);
wave_b_switch=1.0;
}
else if (g>=b && g>=r) //green brightest
{
wave_b_switch=b*(1/g);
wave_r_switch=r*(1/g);
wave_g_switch=1.0;
}
glColor4f(wave_r_switch, wave_g_switch, wave_b_switch, temp_a * masterAlpha);
}
else
{
glColor4f(r, g, b, temp_a * masterAlpha);
}
}
void MilkdropWaveform::WaveformMath(RenderContext &context)
{
int i;
float r, theta;
float offset;
float wave_x_temp=0;
float wave_y_temp=0;
float cos_rot;
float sin_rot;
offset=x-.5;
float temp_y;
two_waves = false;
loop = false;
switch(mode)
{
case Circle:
{
loop = true;
rot = 0;
aspectScale=1.0;
temp_y=-1*(y-1.0);
samples = 0? 512-32 : context.beatDetect->pcm->numsamples;
float inv_nverts_minus_one = 1.0f/(float)(samples);
float last_value = context.beatDetect->pcm->pcmdataR[samples-1]+context.beatDetect->pcm->pcmdataL[samples-1];
float first_value = context.beatDetect->pcm->pcmdataR[0]+context.beatDetect->pcm->pcmdataL[0];
float offset = first_value-last_value;
for ( int i=0;i<samples;i++)
{
float value = context.beatDetect->pcm->pcmdataR[i]+context.beatDetect->pcm->pcmdataL[i];
value += offset * (i/(float)samples);
r=(0.5 + 0.4f*.12*value*scale + mystery)*.5;
theta=i*inv_nverts_minus_one*6.28f + context.time*0.2f;
wavearray[i][0]=(r*cos(theta)*(context.aspectCorrect? context.aspectRatio : 1.0)+x);
wavearray[i][1]=(r*sin(theta)+temp_y);
}
}
break;
case RadialBlob://circularly moving waveform
rot = 0;
aspectScale = context.aspectRatio;
temp_y=-1*(y-1.0);
samples = 512-32;
for ( int i=0;i<512-32;i++)
{
theta=context.beatDetect->pcm->pcmdataL[i+32]*0.06*scale * 1.57 + context.time*2.3;
r=(0.53 + 0.43*context.beatDetect->pcm->pcmdataR[i]*0.12*scale+ mystery)*.5;
wavearray[i][0]=(r*cos(theta)*(context.aspectCorrect ? context.aspectRatio : 1.0)+x);
wavearray[i][1]=(r*sin(theta)+temp_y);
}
break;
case Blob2://EXPERIMENTAL
temp_y=-1*(y-1.0);
rot = 0;
aspectScale =1.0;
samples = 512-32;
for ( int i=0;i<512-32;i++)
{
wavearray[i][0]=(context.beatDetect->pcm->pcmdataR[i]*scale*0.5*(context.aspectCorrect ? context.aspectRatio : 1.0) + x);
wavearray[i][1]=(context.beatDetect->pcm->pcmdataL[i+32]*scale*0.5 + temp_y);
}
break;
case Blob3://EXPERIMENTAL
temp_y=-1*(y-1.0);
rot = 0;
aspectScale =1.0;
samples = 512-32;
for ( int i=0;i<512-32;i++)
{
wavearray[i][0]=(context.beatDetect->pcm->pcmdataR[i] * scale*0.5 + x);
wavearray[i][1]=( (context.beatDetect->pcm->pcmdataL[i+32]*scale*0.5 + temp_y));
}
break;
case DerivativeLine://single x-axis derivative waveform
{
rot =-mystery*90;
aspectScale=1.0;
temp_y=-1*(y-1.0);
float w1 = 0.45f + 0.5f*(mystery*0.5f + 0.5f);
float w2 = 1.0f - w1;
float xx[512], yy[512];
samples = 512-32;
for (int i=0; i<512-32; i++)
{
xx[i] = -1.0f + 2.0f*(i/(512.0-32.0)) + x;
yy[i] =0.4* context.beatDetect->pcm->pcmdataL[i]*0.47f*scale + temp_y;
xx[i] += 0.4*context.beatDetect->pcm->pcmdataR[i]*0.44f*scale;
if (i>1)
{
xx[i] = xx[i]*w2 + w1*(xx[i-1]*2.0f - xx[i-2]);
yy[i] = yy[i]*w2 + w1*(yy[i-1]*2.0f - yy[i-2]);
}
wavearray[i][0]=xx[i];
wavearray[i][1]=yy[i];
} }
break;
case Blob5://EXPERIMENTAL
rot = 0;
aspectScale =1.0;
temp_y=-1*(y-1.0);
cos_rot = cosf(context.time*0.3f);
sin_rot = sinf(context.time*0.3f);
samples = 512-32;
for ( int i=0;i<512-32;i++)
{
float x0 = (context.beatDetect->pcm->pcmdataR[i]*context.beatDetect->pcm->pcmdataL[i+32] + context.beatDetect->pcm->pcmdataL[i+32]*context.beatDetect->pcm->pcmdataR[i]);
float y0 = (context.beatDetect->pcm->pcmdataR[i]*context.beatDetect->pcm->pcmdataR[i] - context.beatDetect->pcm->pcmdataL[i+32]*context.beatDetect->pcm->pcmdataL[i+32]);
wavearray[i][0]=((x0*cos_rot - y0*sin_rot)*scale*0.5*(context.aspectCorrect ? context.aspectRatio : 1.0) + x);
wavearray[i][1]=( (x0*sin_rot + y0*cos_rot)*scale*0.5 + temp_y);
}
break;
case Line://single waveform
wave_x_temp=-2*0.4142*(fabs(fabs(mystery)-.5)-.5);
rot = -mystery*90;
aspectScale =1.0+wave_x_temp;
wave_x_temp=-1*(x-1.0);
samples = 0 ? 512-32 : context.beatDetect->pcm->numsamples;
for ( int i=0;i< samples;i++)
{
wavearray[i][0]=i/(float) samples;
wavearray[i][1]=context.beatDetect->pcm->pcmdataR[i]*.04*scale+wave_x_temp;
}
// printf("%f %f\n",renderTarget->texsize*wave_y_temp,wave_y_temp);
break;
case DoubleLine://dual waveforms
wave_x_temp=-2*0.4142*(fabs(fabs(mystery)-.5)-.5);
rot = -mystery*90;
aspectScale =1.0+wave_x_temp;
samples = 0 ? 512-32 : context.beatDetect->pcm->numsamples;
two_waves = true;
double y_adj = y*y*.5;
wave_y_temp=-1*(x-1);
for ( int i=0;i<samples;i++)
{
wavearray[i][0]=i/((float) samples);
wavearray[i][1]= context.beatDetect->pcm->pcmdataL[i]*.04*scale+(wave_y_temp+y_adj);
}
for ( int i=0;i<samples;i++)
{
wavearray2[i][0]=i/((float) samples);
wavearray2[i][1]=context.beatDetect->pcm->pcmdataR[i]*.04*scale+(wave_y_temp-y_adj);
}
break;
}
}

View File

@ -0,0 +1,65 @@
/*
* MilkdropWaveform.hpp
*
* Created on: Jun 25, 2008
* Author: pete
*/
#ifndef MILKDROPWAVEFORM_HPP_
#define MILKDROPWAVEFORM_HPP_
#include "Renderable.hpp"
enum MilkdropWaveformMode
{
Circle=0, RadialBlob, Blob2, Blob3, DerivativeLine, Blob5, Line, DoubleLine
};
class MilkdropWaveform : public RenderItem
{
public:
float x;
float y;
float r;
float g;
float b;
float a;
float mystery;
MilkdropWaveformMode mode;
bool additive;
bool dots;
bool thick;
bool modulateAlphaByVolume;
bool maximizeColors;
float scale;
float smoothing;
MilkdropWaveform();
void Draw(RenderContext &context);
float modOpacityStart;
float modOpacityEnd;
private:
float temp_a;
float rot;
float aspectScale;
int samples;
bool two_waves;
bool loop;
float wavearray[2048][2];
float wavearray2[2048][2];
void MaximizeColors(RenderContext &context);
void ModulateOpacityByVolume(RenderContext &context);
void WaveformMath(RenderContext &context);
};
#endif /* MILKDROPWAVEFORM_HPP_ */

View File

@ -0,0 +1,48 @@
#include <math.h>
#include <algorithm>
#include "PerPixelMesh.hpp"
#include "omptl/omptl"
#include "omptl/omptl_algorithm"
PerPixelMesh::PerPixelMesh(int width, int height) : width(width), height(height), size (width * height),
p(width * height, Point(0,0)),
p_original(width * height, Point(0,0)),
identity(width * height, PerPixelContext(0,0,0,0,0,0))
{
for (int j=0;j<height;j++)
for(int i=0;i<width;i++)
{
int index = j * width + i;
float xval=i/(float)(width-1);
float yval=-((j/(float)(height-1))-1);
p[index].x = xval;
p[index].y = yval;
p_original[index].x = xval;
p_original[index].y = yval;
identity[index].x= xval;
identity[index].y= yval;
//identity[index].x= (xval-.5)*2;
//identity[index].y= (yval-.5)*2;
identity[index].i= i;
identity[index].j= j;
identity[index].rad=hypot ( ( xval-.5 ) *2, ( yval-.5 ) *2 ) * .7071067;
identity[index].theta=atan2 ( ( yval-.5 ) *2 , ( xval-.5 ) *2 );
}
}
void PerPixelMesh::Reset()
{
omptl::copy(p_original.begin(), p_original.end(), p.begin());
}
Point::Point(float x, float y)
: x(x), y(y) {}
PerPixelContext::PerPixelContext(float x, float y, float rad, float theta, int i, int j)
: x(x), y(y), rad(rad), theta(theta), i(i), j(j) {}

View File

@ -0,0 +1,45 @@
#ifndef PerPixelMesh_HPP
#define PerPixelMesh_HPP
#include <vector>
struct Point
{
float x;
float y;
Point(float x, float y);
};
struct PerPixelContext
{
float x;
float y;
float rad;
float theta;
int i;
int j;
PerPixelContext(float x, float y, float rad, float theta, int i, int j);
};
class PerPixelMesh
{
public:
int width;
int height;
int size;
std::vector<Point> p;
std::vector<Point> p_original;
std::vector<PerPixelContext> identity;
PerPixelMesh(int width, int height);
void Reset();
};
#endif

View File

@ -0,0 +1,53 @@
/*
* PerlinNoise.cpp
*
* Created on: Jul 11, 2008
* Author: pete
*/
#include "PerlinNoise.hpp"
#include <iostream>
#include <stdlib.h>
PerlinNoise::PerlinNoise()
{
for (int x = 0; x < 256;x++)
for (int y = 0; y < 256;y++)
noise_lq[x][y] = noise(x , y);
for (int x = 0; x < 32;x++)
for (int y = 0; y < 32;y++)
noise_lq_lite[x][y] = noise(4*x,16*y);
for (int x = 0; x < 256;x++)
for (int y = 0; y < 256;y++)
noise_mq[x][y] = InterpolatedNoise((float)x/(float)2.0,(float)y/(float)2.0);
for (int x = 0; x < 256;x++)
for (int y = 0; y < 256;y++)
noise_hq[x][y] = InterpolatedNoise((float)x/(float)3.0,(float)y/(float)3.0);
for (int x = 0; x < 32;x++)
for (int y = 0; y < 32;y++)
for (int z = 0; z < 32;z++)
noise_lq_vol[x][y][z] = noise(x,y,z);
for (int x = 0; x < 32;x++)
for (int y = 0; y < 32;y++)
for (int z = 0; z < 32;z++)
noise_hq_vol[x][y][z] = noise(x,y,z);//perlin_noise_3d(x,y,z,6121,7,seed3,0.5,64);
int seed = rand()%1000;
int size = 512;
int octaves = sqrt((double)size);
for (int x = 0; x < size;x++)
for (int y = 0; y < size;y++)
noise_perlin[x][y] = perlin_noise_2d(x,y,6321,octaves,seed,0.5,size/4);
}
PerlinNoise::~PerlinNoise()
{
// TODO Auto-generated destructor stub
}

View File

@ -0,0 +1,241 @@
/*
* PerlinNoise.hpp
*
* Created on: Jul 11, 2008
* Author: pete
*/
#ifndef PERLINNOISE_HPP_
#define PERLINNOISE_HPP_
#include <math.h>
class PerlinNoise
{
public:
float noise_lq[256][256];
float noise_lq_lite[32][32];
float noise_mq[256][256];
float noise_hq[256][256];
float noise_perlin[512][512];
float noise_lq_vol[32][32][32];
float noise_hq_vol[32][32][32];
PerlinNoise();
virtual ~PerlinNoise();
private:
static inline float noise( int x)
{
x = (x<<13)^x;
return (((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff) / 2147483648.0);
}
static inline float noise(int x, int y)
{
int n = x + y * 57;
return noise(n);
}
static inline float noise(int x, int y, int z)
{
int n = x + y * 57 + z * 141;
return noise(n);
}
static inline float cos_interp(float a, float b, float x)
{
float ft = x * 3.1415927;
float f = (1 - cos(ft)) * .5;
return a*(1-f) + b*f;
}
static inline float cubic_interp(float v0, float v1, float v2, float v3, float x)
{
float P = (v3 - v2) - (v0 - v1);
float Q = (v0 - v1) - P;
float R = v2 - v0;
return P*pow(x,3) + Q * pow(x,2) + R*x + v1;
}
static inline float InterpolatedNoise(float x, float y)
{
int integer_X = int(x);
float fractional_X = x - integer_X;
int integer_Y = int(y);
float fractional_Y = y - integer_Y;
float a0 = noise(integer_X - 1, integer_Y - 1);
float a1 = noise(integer_X, integer_Y - 1);
float a2 = noise(integer_X + 1, integer_Y - 1);
float a3 = noise(integer_X + 2, integer_Y - 1);
float x0 = noise(integer_X - 1, integer_Y);
float x1 = noise(integer_X, integer_Y);
float x2 = noise(integer_X + 1, integer_Y);
float x3 = noise(integer_X + 2, integer_Y);
float y0 = noise(integer_X + 0, integer_Y + 1);
float y1 = noise(integer_X, integer_Y + 1);
float y2 = noise(integer_X + 1, integer_Y + 1);
float y3 = noise(integer_X + 2, integer_Y + 1);
float b0 = noise(integer_X - 1, integer_Y + 2);
float b1 = noise(integer_X, integer_Y + 2);
float b2 = noise(integer_X + 1, integer_Y + 2);
float b3 = noise(integer_X + 2, integer_Y + 2);
float i0 = cubic_interp(a0 , a1, a2, a3, fractional_X);
float i1 = cubic_interp(x0 , x1, x2, x3, fractional_X);
float i2 = cubic_interp(y0 , y1, y2, y3, fractional_X);
float i3 = cubic_interp(b0 , b1, b2, b3, fractional_X);
return cubic_interp(i0, i1 , i2 , i3, fractional_Y);
}
static inline float perlin_octave_2d(float x,float y, int width, int seed, float period)
{
float freq=1/(float)(period);
int num=(int)(width*freq);
int step_x=(int)(x*freq);
int step_y=(int)(y*freq);
float zone_x=x*freq-step_x;
float zone_y=y*freq-step_y;
int box=step_x+step_y*num;
int noisedata=(box+seed);
float u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
float a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
float b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
float v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
float value=cubic_interp(u,a,b,v,zone_y);
return value;
}
static inline float perlin_octave_2d_cos(float x,float y, int width, int seed, float period)
{
float freq=1/(float)(period);
int num=(int)(width*freq);
int step_x=(int)(x*freq);
int step_y=(int)(y*freq);
float zone_x=x*freq-step_x;
float zone_y=y*freq-step_y;
int box=step_x+step_y*num;
int noisedata=(box+seed);
float a=cos_interp(noise(noisedata),noise(noisedata+1),zone_x);
float b=cos_interp(noise(noisedata+num),noise(noisedata+1+num),zone_x);
float value=cos_interp(a,b,zone_y);
return value;
}
static inline float perlin_octave_3d(float x,float y, float z,int width, int seed, float period)
{
float freq=1/(float)(period);
int num=(int)(width*freq);
int step_x=(int)(x*freq);
int step_y=(int)(y*freq);
int step_z=(int)(z*freq);
float zone_x=x*freq-step_x;
float zone_y=y*freq-step_y;
float zone_z=z*freq-step_z;
int boxB=step_x+step_y+step_z*num;
int boxC=step_x+step_y+step_z*(num+1);
int boxD=step_x+step_y+step_z*(num+2);
int boxA=step_x+step_y+step_z*(num-1);
float u,a,b,v,noisedata,box;
box = boxA;
noisedata=(box+seed);
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
float A=cubic_interp(u,a,b,v,zone_y);
box = boxB;
noisedata=(box+seed);
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
float B=cubic_interp(u,a,b,v,zone_y);
box = boxC;
noisedata=(box+seed);
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
float C=cubic_interp(u,a,b,v,zone_y);
box = boxD;
noisedata=(box+seed);
u=cubic_interp(noise(noisedata-num-1),noise(noisedata-num),noise(noisedata-num+1),noise(noisedata-num+2),zone_x);
a=cubic_interp(noise(noisedata-1),noise(noisedata),noise(noisedata+1),noise(noisedata+2),zone_x);
b=cubic_interp(noise(noisedata+num -1),noise(noisedata+num),noise(noisedata+1+num),noise(noisedata+2+num),zone_x);
v=cubic_interp(noise(noisedata+2*num -1),noise(noisedata+2*num),noise(noisedata+1+2*num),noise(noisedata+2+2*num),zone_x);
float D=cubic_interp(u,a,b,v,zone_y);
float value =cubic_interp(A,B,C,D,zone_z);
return value;
}
static inline float perlin_noise_2d(int x, int y, int width, int octaves, int seed, float persistance, float basePeriod)
{
float p = persistance;
float val = 0.0;
for (int i = 0; i<octaves;i++)
{
val += perlin_octave_2d_cos(x,y,width,seed,basePeriod) * p;
basePeriod *= 0.5;
p *= persistance;
}
return val;
}
static inline float perlin_noise_3d(int x, int y, int z, int width, int octaves, int seed, float persistance, float basePeriod)
{
float p = persistance;
float val = 0.0;
for (int i = 0; i<octaves;i++)
{
val += perlin_octave_3d(x,y,z,width,seed,basePeriod) * p;
basePeriod *= 0.5;
p *= persistance;
}
return val;
}
};
#endif /* PERLINNOISE_HPP_ */

View File

@ -0,0 +1,49 @@
/*
* Pipeline.cpp
*
* Created on: Jun 17, 2008
* Author: pete
*/
#include "Pipeline.hpp"
#include "wipemalloc.h"
Pipeline::Pipeline() : staticPerPixel(false),gx(0),gy(0),blur1n(1), blur2n(1), blur3n(1),
blur1x(1), blur2x(1), blur3x(1),
blur1ed(1){}
void Pipeline::setStaticPerPixel(int gx, int gy)
{
staticPerPixel = true;
this->gx = gx;
this->gy = gy;
this->x_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( int x = 0; x < gx; x++ )
{
this->x_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
this->y_mesh= ( float ** ) wipemalloc ( gx * sizeof ( float * ) );
for ( int x = 0; x < gx; x++ )
{
this->y_mesh[x] = ( float * ) wipemalloc ( gy * sizeof ( float ) );
}
}
Pipeline::~Pipeline()
{
if (staticPerPixel)
{
for ( int x = 0; x < this->gx; x++ )
{
free(this->x_mesh[x]);
free(this->y_mesh[x]);
}
free(x_mesh);
free(y_mesh);
}
}
//void Pipeline::Render(const BeatDetect &music, const PipelineContext &context){}
Point Pipeline::PerPixel(Point p, const PerPixelContext context)
{return p;}

View File

@ -0,0 +1,56 @@
#ifndef Pipeline_HPP
#define Pipeline_HPP
#include <vector>
#include "PerPixelMesh.hpp"
#include "Renderable.hpp"
#include "Filters.hpp"
#include "PipelineContext.hpp"
#include "Shader.hpp"
#include "../Common.hpp"
//This class is the input to projectM's renderer
//
//Most implemenatations should implement PerPixel in order to get multi-threaded
//dynamic PerPixel equations. If you MUST (ie Milkdrop compatability), you can use the
//setStaticPerPixel function and fill in x_mesh and y_mesh yourself.
class Pipeline
{
public:
//static per pixel stuff
bool staticPerPixel;
int gx;
int gy;
float** x_mesh;
float** y_mesh;
//end static per pixel
bool textureWrap;
float screenDecay;
//variables passed to pixel shaders
float q[NUM_Q_VARIABLES];
//blur settings n=bias x=scale
float blur1n;
float blur2n;
float blur3n;
float blur1x;
float blur2x;
float blur3x;
float blur1ed;
Shader warpShader;
Shader compositeShader;
std::vector<RenderItem*> drawables;
std::vector<RenderItem*> compositeDrawables;
Pipeline();
void setStaticPerPixel(int gx, int gy);
virtual ~Pipeline();
virtual Point PerPixel(Point p, const PerPixelContext context);
};
#endif

View File

@ -0,0 +1,11 @@
/*
* PipelineContext.cpp
*
* Created on: Jun 22, 2008
* Author: pete
*/
#include "PipelineContext.hpp"
PipelineContext::PipelineContext() {}
PipelineContext::~PipelineContext() {}

View File

@ -0,0 +1,23 @@
/*
* PipelineContext.hpp
*
* Created on: Jun 22, 2008
* Author: pete
*/
#ifndef PIPELINECONTEXT_HPP_
#define PIPELINECONTEXT_HPP_
class PipelineContext
{
public:
int fps;
float time;
int frame;
float progress;
PipelineContext();
virtual ~PipelineContext();
};
#endif /* PIPELINECONTEXT_HPP_ */

View File

@ -0,0 +1,13 @@
/*
* RenderItemDistanceMetric.cpp
*
* Created on: Feb 18, 2009
* Author: struktured
*/
#include "RenderItemDistanceMetric.hpp"
// Assumes [0, 1] distance space because it's easy to manage with overflow
// Underflow is obviously possible though.
const double RenderItemDistanceMetric::NOT_COMPARABLE_VALUE
(1.0);

View File

@ -0,0 +1,145 @@
/*
* RenderItemDistanceMetric.h
*
* Created on: Feb 16, 2009
* Author: struktured
*/
#ifndef RenderItemDISTANCEMETRIC_H_
#define RenderItemDISTANCEMETRIC_H_
#include "Common.hpp"
#include "Renderable.hpp"
#include <limits>
#include <functional>
#include <map>
/// Compares two render items and returns zero if they are virtually equivalent and large values
/// when they are dissimilar. If two render items cannot be compared, NOT_COMPARABLE_VALUE is returned.
class RenderItemDistanceMetric : public std::binary_function<const RenderItem*, const RenderItem*, double> {
public:
const static double NOT_COMPARABLE_VALUE;
virtual double operator()(const RenderItem * r1, const RenderItem * r2) const = 0;
virtual TypeIdPair typeIdPair() const = 0;
};
// A base class to construct render item distance metrics. Just specify your two concrete
// render item types as template parameters and override the computeDistance() function.
template <class R1, class R2>
class RenderItemDistance : public RenderItemDistanceMetric {
protected:
// Override to create your own distance fmetric for your specified custom types.
virtual double computeDistance(const R1 * r1, const R2 * r2) const = 0;
public:
inline virtual double operator()(const RenderItem * r1, const RenderItem * r2) const {
if (supported(r1, r2))
return computeDistance(dynamic_cast<const R1*>(r1), dynamic_cast<const R2*>(r2));
else if (supported(r2,r1))
return computeDistance(dynamic_cast<const R1*>(r2), dynamic_cast<const R2*>(r1));
else
return NOT_COMPARABLE_VALUE;
}
// Returns true if and only if r1 and r2 are the same type as or derived from R1, R2 respectively
inline bool supported(const RenderItem * r1, const RenderItem * r2) const {
return dynamic_cast<const R1*>(r1) && dynamic_cast<const R2*>(r2);
//return typeid(r1) == typeid(const R1 *) && typeid(r2) == typeid(const R2 *);
}
inline TypeIdPair typeIdPair() const {
return TypeIdPair(typeid(const R1*).name(), typeid(const R2*).name());
}
};
class RTIRenderItemDistance : public RenderItemDistance<RenderItem, RenderItem> {
public:
RTIRenderItemDistance() {}
virtual ~RTIRenderItemDistance() {}
protected:
virtual inline double computeDistance(const RenderItem * lhs, const RenderItem * rhs) const {
if (typeid(*lhs) == typeid(*rhs)) {
//std::cerr << typeid(*lhs).name() << " and " << typeid(*rhs).name() << "are comparable" << std::endl;
return 0.0;
}
else {
//std::cerr << typeid(*lhs).name() << " and " << typeid(*rhs).name() << "not comparable" << std::endl;
return NOT_COMPARABLE_VALUE;
}
}
};
class ShapeXYDistance : public RenderItemDistance<Shape, Shape> {
public:
ShapeXYDistance() {}
virtual ~ShapeXYDistance() {}
protected:
virtual inline double computeDistance(const Shape * lhs, const Shape * rhs) const {
return (meanSquaredError(lhs->x, rhs->x) + meanSquaredError(lhs->y, rhs->y)) / 2;
}
};
class MasterRenderItemDistance : public RenderItemDistance<RenderItem, RenderItem> {
typedef std::map<TypeIdPair, RenderItemDistanceMetric*> DistanceMetricMap;
public:
MasterRenderItemDistance() {}
virtual ~MasterRenderItemDistance() {}
inline void addMetric(RenderItemDistanceMetric * fun) {
_distanceMetricMap[fun->typeIdPair()] = fun;
}
protected:
virtual inline double computeDistance(const RenderItem * lhs, const RenderItem * rhs) const {
RenderItemDistanceMetric * metric;
TypeIdPair pair(typeid(lhs), typeid(rhs));
// If specialized metric exists, use it to get higher granularity
// of correctness
if (_distanceMetricMap.count(pair)) {
metric = _distanceMetricMap[pair];
} else if (_distanceMetricMap.count(pair = TypeIdPair(typeid(rhs), typeid(lhs)))) {
metric = _distanceMetricMap[pair];
} else { // Failing that, use rtti && shape distance if its a shape type
const double rttiError = _rttiDistance(lhs,rhs);
/// @bug This is a non elegant approach to supporting shape distance
if (rttiError == 0 && _shapeXYDistance.supported(lhs,rhs))
return _shapeXYDistance(lhs, rhs);
else return rttiError;
}
return (*metric)(lhs, rhs);
}
private:
mutable RTIRenderItemDistance _rttiDistance;
mutable ShapeXYDistance _shapeXYDistance;
mutable DistanceMetricMap _distanceMetricMap;
};
#endif /* RenderItemDISTANCEMETRIC_H_ */

View File

@ -0,0 +1,34 @@
#include "RenderItemMatcher.hpp"
double RenderItemMatcher::computeMatching(const RenderItemList & lhs, const RenderItemList & rhs) const {
for (int i = 0; i < lhs.size();i++) {
int j;
for (j = 0; j < rhs.size();j++)
_weights[i][j] = _distanceFunction(lhs[i], rhs[j]);
for (; j < lhs.size();j++)
_weights[i][j] = RenderItemDistanceMetric::NOT_COMPARABLE_VALUE;
}
const double error = _hungarianMethod(_weights, lhs.size());
//std::cout << "[computeMatching] total error is " << error << std::endl;
return error;
}
void RenderItemMatcher::setMatches
(const RenderItemList & lhs_src, const RenderItemList & rhs_src) const {
for (int i = 0; i < lhs_src.size();i++) {
const int j = _hungarianMethod.matching(i);
// hack
if (true || _weights[i][j] == RenderItemDistanceMetric::NOT_COMPARABLE_VALUE) {
_results.unmatchedLeft.push_back(lhs_src[i]);
_results.unmatchedRight.push_back(rhs_src[i]);
} else {
_results.matches.push_back(std::make_pair(lhs_src[i], rhs_src[j]));
}
}
}

View File

@ -0,0 +1,77 @@
/*
* RenderItemMatcher.hpp
*
* Created on: Feb 16, 2009
* Author: struktured
*/
#ifndef RenderItemMatcher_HPP
#define RenderItemMatcher_HPP
#include "RenderItemDistanceMetric.hpp"
#include <vector>
#include <map>
#include <iostream>
#include "HungarianMethod.hpp"
typedef std::vector<std::pair<RenderItem*, RenderItem*> > RenderItemMatchList;
class MatchResults;
class RenderItemMatcher : public std::binary_function<RenderItemList, RenderItemList, MatchResults> {
public:
struct MatchResults {
RenderItemMatchList matches;
std::vector<RenderItem*> unmatchedLeft;
std::vector<RenderItem*> unmatchedRight;
double error;
};
static const std::size_t MAXIMUM_SET_SIZE = 1000;
/// Computes an optimal matching between two renderable item sets.
/// @param lhs the "left-hand side" list of render items.
/// @param rhs the "right-hand side" list of render items.
/// @returns a list of match pairs, possibly self referencing, and an error estimate of the matching.
inline virtual void operator()(const RenderItemList & lhs, const RenderItemList & rhs) const {
// Ensure the first argument is greater than next to aid the helper function's logic.
if (lhs.size() >= rhs.size()) {
_results.error = computeMatching(lhs, rhs);
setMatches(lhs, rhs);
} else {
_results.error = computeMatching(rhs, lhs);
setMatches(rhs, lhs);
}
}
RenderItemMatcher() {}
virtual ~RenderItemMatcher() {}
inline MatchResults & matchResults() { return _results; }
inline double weight(int i, int j) const { return _weights[i][j]; }
MasterRenderItemDistance & distanceFunction() { return _distanceFunction; }
private:
mutable HungarianMethod<MAXIMUM_SET_SIZE> _hungarianMethod;
mutable double _weights[MAXIMUM_SET_SIZE][MAXIMUM_SET_SIZE];
mutable MatchResults _results;
/// @idea interface this entirely allow overriding of its type.
mutable MasterRenderItemDistance _distanceFunction;
double computeMatching(const RenderItemList & lhs, const RenderItemList & rhs) const;
void setMatches(const RenderItemList & lhs_src, const RenderItemList & rhs_src) const;
};
#endif

View File

@ -0,0 +1,236 @@
/*
* RenderItemMergeFunction.hpp
*
* Created on: Feb 16, 2009
* Author: struktured
*/
#ifndef RenderItemMergeFunction_HPP_
#define RenderItemMergeFunction_HPP_
#include "Common.hpp"
#include "Renderable.hpp"
#include "Waveform.hpp"
#include <limits>
#include <functional>
#include <map>
template <class T>
inline T interpolate(T a, T b, float ratio)
{
return (ratio*a + (1-ratio)*b) * 0.5;
}
template <>
inline int interpolate(int a, int b, float ratio)
{
return (int)(ratio*(float)a + (1-ratio)*(float)b) * 0.5;
}
template <>
inline bool interpolate(bool a, bool b, float ratio)
{
return (ratio >= 0.5) ? a : b;
}
/// Merges two render items and returns zero if they are virtually equivalent and large values
/// when they are dissimilar. If two render items cannot be compared, NOT_COMPARABLE_VALUE is returned.
class RenderItemMergeFunction {
public:
virtual RenderItem * operator()(const RenderItem * r1, const RenderItem * r2, double ratio) const = 0;
virtual TypeIdPair typeIdPair() const = 0;
};
/// A base class to construct render item distance mergeFunctions. Just specify your two concrete
/// render item types as template parameters and override the computeMerge() function.
template <class R1, class R2=R1, class R3=R2>
class RenderItemMerge : public RenderItemMergeFunction {
protected:
/// Override to create your own distance mergeFunction for your specified custom types.
virtual R3 * computeMerge(const R1 * r1, const R2 * r2, double ratio) const = 0;
public:
inline virtual R3 * operator()(const RenderItem * r1, const RenderItem * r2, double ratio) const {
if (supported(r1, r2))
return computeMerge(dynamic_cast<const R1*>(r1), dynamic_cast<const R2*>(r2), ratio);
else if (supported(r2,r1))
return computeMerge(dynamic_cast<const R1*>(r2), dynamic_cast<const R2*>(r1), ratio);
else
return 0;
}
/// Returns true if and only if r1 and r2 are of type R1 and R2 respectively.
inline bool supported(const RenderItem * r1, const RenderItem * r2) const {
return typeid(r1) == typeid(const R1 *) && typeid(r2) == typeid(const R2 *);
}
inline TypeIdPair typeIdPair() const {
return TypeIdPair(typeid(const R1*).name(), typeid(const R2*).name());
}
};
class ShapeMerge : public RenderItemMerge<Shape> {
public:
ShapeMerge() {}
virtual ~ShapeMerge() {}
protected:
virtual inline Shape * computeMerge(const Shape * lhs, const Shape * rhs, double ratio) const {
Shape * ret = new Shape();
Shape & target = *ret;
target.x = interpolate(lhs->x, rhs->x, ratio);
target.y = interpolate(lhs->y, rhs->y, ratio);
target.a = interpolate(lhs->a, rhs->a, ratio);
target.a2 = interpolate(lhs->a2, rhs->a2, ratio);
target.r = interpolate(lhs->r, rhs->r, ratio);
target.r2 = interpolate(lhs->r2, rhs->r2, ratio);
target.g = interpolate(lhs->g, rhs->g, ratio);
target.g2 = interpolate(lhs->g2, rhs->g2, ratio);
target.b = interpolate(lhs->b, rhs->b, ratio);
target.b2 = interpolate(lhs->b2, rhs->b2, ratio);
target.ang = interpolate(lhs->ang, rhs->ang, ratio);
target.radius = interpolate(lhs->radius, rhs->radius, ratio);
target.tex_ang = interpolate(lhs->tex_ang, rhs->tex_ang, ratio);
target.tex_zoom = interpolate(lhs->tex_zoom, rhs->tex_zoom, ratio);
target.border_a = interpolate(lhs->border_a, rhs->border_a, ratio);
target.border_r = interpolate(lhs->border_r, rhs->border_r, ratio);
target.border_g = interpolate(lhs->border_g, rhs->border_g, ratio);
target.border_b = interpolate(lhs->border_b, rhs->border_b, ratio);
target.sides = interpolate(lhs->sides, rhs->sides, ratio);
target.additive = interpolate(lhs->additive, rhs->additive, ratio);
target.textured = interpolate(lhs->textured, rhs->textured, ratio);
target.thickOutline = interpolate(lhs->thickOutline, rhs->thickOutline, ratio);
target.enabled = interpolate(lhs->enabled, rhs->enabled, ratio);
target.masterAlpha = interpolate(lhs->masterAlpha, rhs->masterAlpha, ratio);
target.imageUrl = (ratio > 0.5) ? lhs->imageUrl : rhs->imageUrl, ratio;
return ret;
}
};
class BorderMerge : public RenderItemMerge<Border> {
public:
BorderMerge() {}
virtual ~BorderMerge() {}
protected:
virtual inline Border * computeMerge(const Border * lhs, const Border * rhs, double ratio) const
{
Border * ret = new Border();
Border & target = *ret;
target.inner_a = interpolate(lhs->inner_a, rhs->inner_a, ratio);
target.inner_r = interpolate(lhs->inner_r, rhs->inner_r, ratio);
target.inner_g = interpolate(lhs->inner_g, rhs->inner_g, ratio);
target.inner_b = interpolate(lhs->inner_b, rhs->inner_b, ratio);
target.inner_size = interpolate(lhs->inner_size, rhs->inner_size, ratio);
target.outer_a = interpolate(lhs->outer_a, rhs->outer_a, ratio);
target.outer_r = interpolate(lhs->outer_r, rhs->outer_r, ratio);
target.outer_g = interpolate(lhs->outer_g, rhs->outer_g, ratio);
target.outer_b = interpolate(lhs->outer_b, rhs->outer_b, ratio);
target.outer_size = interpolate(lhs->outer_size, rhs->outer_size, ratio);
target.masterAlpha = interpolate(lhs->masterAlpha, rhs->masterAlpha, ratio);
return ret;
}
};
class WaveformMerge : public RenderItemMerge<Waveform> {
public:
WaveformMerge() {}
virtual ~WaveformMerge() {}
protected:
/// @BUG unimplemented
virtual inline Waveform * computeMerge(const Waveform * lhs, const Waveform * rhs, double ratio) const
{
return 0;
/*
Waveform * ret = new Waveform();
Waveform & target = *ret;
target.additive = interpolate(lhs->additive, rhs->additive, ratio);
target.dots = interpolate(lhs->dots, rhs->dots, ratio);
target.samples = (rhs->samples > lhs-> samples) ? lhs->samples : rhs->samples;
target.scaling = interpolate(lhs->scaling, rhs->scaling, ratio);
target.sep = interpolate(lhs->sep, rhs->sep, ratio);
target.smoothing = interpolate(lhs->smoothing, rhs->smoothing, ratio);
target.spectrum = interpolate(lhs->spectrum, rhs->spectrum, ratio);
target.thick = interpolate(lhs->thick, rhs->thick, ratio);
target.masterAlpha = interpolate(lhs->masterAlpha, rhs->masterAlpha, ratio);
return ret;
*/
}
};
/// Use as the top level merge function. It stores a map of all other
/// merge functions, using the function that fits best with the
/// incoming type parameters.
class MasterRenderItemMerge : public RenderItemMerge<RenderItem> {
typedef std::map<TypeIdPair, RenderItemMergeFunction*> MergeFunctionMap;
public:
MasterRenderItemMerge() {}
virtual ~MasterRenderItemMerge() {}
inline void add(RenderItemMergeFunction * fun) {
_mergeFunctionMap[fun->typeIdPair()] = fun;
}
protected:
virtual inline RenderItem * computeMerge(const RenderItem * lhs, const RenderItem * rhs, double ratio) const {
RenderItemMergeFunction * mergeFunction;
TypeIdPair pair(typeid(lhs), typeid(rhs));
if (_mergeFunctionMap.count(pair)) {
mergeFunction = _mergeFunctionMap[pair];
} else if (_mergeFunctionMap.count(pair = TypeIdPair(typeid(rhs), typeid(lhs)))) {
mergeFunction = _mergeFunctionMap[pair];
} else {
mergeFunction = 0;
}
// If specialized mergeFunction exists, use it to get higher granularity
// of correctness
if (mergeFunction)
return (*mergeFunction)(lhs, rhs, ratio);
else
return 0;
}
private:
mutable MergeFunctionMap _mergeFunctionMap;
};
#endif /* RenderItemMergeFunction_HPP_ */

View File

@ -0,0 +1,355 @@
#include "Common.hpp"
#ifdef USE_GLES1
#include <GLES/gl.h>
#else
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#endif
#include "Renderable.hpp"
#include <math.h>
typedef float floatPair[2];
typedef float floatTriple[3];
typedef float floatQuad[4];
RenderContext::RenderContext()
: time(0),texsize(512), aspectRatio(1), aspectCorrect(false){};
RenderItem::RenderItem():masterAlpha(1){}
DarkenCenter::DarkenCenter():RenderItem(){}
MotionVectors::MotionVectors():RenderItem(){}
Border::Border():RenderItem(){}
void DarkenCenter::Draw(RenderContext &context)
{
//float unit=0.05f;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float colors[6][4] = {{0, 0, 0, (3.0f/32.0f) * masterAlpha},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}};
float points[6][2] = {{ 0.5, 0.5},
{ 0.45, 0.5},
{ 0.5, 0.45},
{ 0.55, 0.5},
{ 0.5, 0.55},
{ 0.45, 0.5}};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2,GL_FLOAT,0,points);
glColorPointer(4,GL_FLOAT,0,colors);
glDrawArrays(GL_TRIANGLE_FAN,0,6);
}
Shape::Shape():RenderItem()
{
std::string imageUrl = "";
sides = 4;
thickOutline = false;
enabled = true;
additive = false;
textured = false;
tex_zoom = 1.0;
tex_ang = 0.0;
x = 0.5;
y = 0.5;
radius = 1.0;
ang = 0.0;
r = 0.0; /* red color value */
g = 0.0; /* green color value */
b = 0.0; /* blue color value */
a = 0.0; /* alpha color value */
r2 = 0.0; /* red color value */
g2 = 0.0; /* green color value */
b2 = 0.0; /* blue color value */
a2 = 0.0; /* alpha color value */
border_r = 0.0; /* red color value */
border_g = 0.0; /* green color value */
border_b = 0.0; /* blue color value */
border_a = 0.0; /* alpha color value */
}
void Shape::Draw(RenderContext &context)
{
float xval, yval;
float t;
// printf("drawing shape %f\n", ang);
float temp_radius= radius*(.707*.707*.707*1.04);
//Additive Drawing or Overwrite
if ( additive==0) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else glBlendFunc(GL_SRC_ALPHA, GL_ONE);
xval= x;
yval= -(y-1);
if ( textured)
{
if (imageUrl !="")
{
GLuint tex= context.textureManager->getTexture(imageUrl);
if (tex != 0)
{
glBindTexture(GL_TEXTURE_2D, tex);
context.aspectRatio=1.0;
}
}
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
floatQuad *colors = new float[sides+2][4];
floatPair *tex = new float[sides+2][2];
floatPair *points = new float[sides+2][2];
//Define the center point of the shape
colors[0][0] = r;
colors[0][1] = g;
colors[0][2] = b;
colors[0][3] = a * masterAlpha;
tex[0][0] = 0.5;
tex[0][1] = 0.5;
points[0][0] = xval;
points[0][1] = yval;
for ( int i=1;i< sides+2;i++)
{
colors[i][0]= r2;
colors[i][1]=g2;
colors[i][2]=b2;
colors[i][3]=a2 * masterAlpha;
t = (i-1)/(float) sides;
tex[i][0] =0.5f + 0.5f*cosf(t*3.1415927f*2 + tex_ang + 3.1415927f*0.25f)*(context.aspectCorrect ? context.aspectRatio : 1.0)/ tex_zoom;
tex[i][1] = 0.5f + 0.5f*sinf(t*3.1415927f*2 + tex_ang + 3.1415927f*0.25f)/ tex_zoom;
points[i][0]=temp_radius*cosf(t*3.1415927f*2 + ang + 3.1415927f*0.25f)*(context.aspectCorrect ? context.aspectRatio : 1.0)+xval;
points[i][1]=temp_radius*sinf(t*3.1415927f*2 + ang + 3.1415927f*0.25f)+yval;
}
glVertexPointer(2,GL_FLOAT,0,points);
glColorPointer(4,GL_FLOAT,0,colors);
glTexCoordPointer(2,GL_FLOAT,0,tex);
glDrawArrays(GL_TRIANGLE_FAN,0,sides+2);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
//Reset Texture state since we might have changed it
/*
if(this->renderTarget->useFBO)
{
glBindTexture( GL_TEXTURE_2D, renderTarget->textureID[1] );
}
else
{
glBindTexture( GL_TEXTURE_2D, renderTarget->textureID[0] );
}
*/
delete[] colors;
delete[] tex;
delete[] points;
}
else
{//Untextured (use color values)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
floatQuad *colors = new float[sides+2][4];
floatPair *points = new float[sides+2][2];
//Define the center point of the shape
colors[0][0]=r;
colors[0][1]=g;
colors[0][2]=b;
colors[0][3]=a * masterAlpha;
points[0][0]=xval;
points[0][1]=yval;
for ( int i=1;i< sides+2;i++)
{
colors[i][0]=r2;
colors[i][1]=g2;
colors[i][2]=b2;
colors[i][3]=a2 * masterAlpha;
t = (i-1)/(float) sides;
points[i][0]=temp_radius*cosf(t*3.1415927f*2 + ang + 3.1415927f*0.25f)*(context.aspectCorrect ? context.aspectRatio : 1.0)+xval;
points[i][1]=temp_radius*sinf(t*3.1415927f*2 + ang + 3.1415927f*0.25f)+yval;
}
glVertexPointer(2,GL_FLOAT,0,points);
glColorPointer(4,GL_FLOAT,0,colors);
glDrawArrays(GL_TRIANGLE_FAN,0,sides+2);
//draw first n-1 triangular pieces
delete[] colors;
delete[] points;
}
if (thickOutline==1) glLineWidth(context.texsize < 512 ? 1 : 2*context.texsize/512);
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
floatPair *points = new float[sides+1][2];
glColor4f( border_r, border_g, border_b, border_a * masterAlpha);
for ( int i=0;i< sides;i++)
{
t = (i-1)/(float) sides;
points[i][0]= temp_radius*cosf(t*3.1415927f*2 + ang + 3.1415927f*0.25f)*(context.aspectCorrect ? context.aspectRatio : 1.0)+xval;
points[i][1]= temp_radius*sinf(t*3.1415927f*2 + ang + 3.1415927f*0.25f)+yval;
}
glVertexPointer(2,GL_FLOAT,0,points);
glDrawArrays(GL_LINE_LOOP,0,sides);
if (thickOutline==1) glLineWidth(context.texsize < 512 ? 1 : context.texsize/512);
delete[] points;
}
void MotionVectors::Draw(RenderContext &context)
{
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
float intervalx=1.0/x_num;
float intervaly=1.0/y_num;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPointSize(length);
glColor4f(r, g, b, a * masterAlpha);
if (x_num + y_num < 600)
{
int size = x_num * y_num ;
floatPair *points = new float[size][2];
for (int x=0;x<(int)x_num;x++)
{
for(int y=0;y<(int)y_num;y++)
{
float lx, ly, lz;
lx = x_offset+x*intervalx;
ly = y_offset+y*intervaly;
points[(x * (int)y_num) + y][0] = lx;
points[(x * (int)y_num) + y][1] = ly;
}
}
glVertexPointer(2,GL_FLOAT,0,points);
glDrawArrays(GL_POINTS,0,size);
delete[] points;
}
}
void Border::Draw(RenderContext &context)
{
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//Draw Borders
float of=outer_size*.5;
float iff=inner_size*.5;
float texof=1.0-of;
//no additive drawing for borders
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(outer_r, outer_g, outer_b, outer_a * masterAlpha);
float pointsA[4][2] = {{0,0},{0,1},{of,0},{of,1}};
glVertexPointer(2,GL_FLOAT,0,pointsA);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
float pointsB[4][2] = {{of,0},{of,of},{texof,0},{texof,of}};
glVertexPointer(2,GL_FLOAT,0,pointsB);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
float pointsC[4][2] = {{texof,0},{texof,1},{1,0},{1,1}};
glVertexPointer(2,GL_FLOAT,0,pointsC);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
float pointsD[4][2] = {{of,1},{of,texof},{texof,1},{texof,texof}};
glVertexPointer(2,GL_FLOAT,0,pointsD);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glColor4f(inner_r, inner_g, inner_b, inner_a * masterAlpha);
glRectd(of, of, of+iff, texof);
glRectd(of+iff, of, texof-iff, of+iff);
glRectd(texof-iff, of, texof, texof);
glRectd(of+iff, texof, texof-iff, texof-iff);
float pointsE[4][2] = {{of,of},{of,texof},{of+iff,of},{of+iff,texof}};
glVertexPointer(2,GL_FLOAT,0,pointsE);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
float pointsF[4][2] = {{of+iff,of},{of+iff,of+iff},{texof-iff,of},{texof-iff,of+iff}};
glVertexPointer(2,GL_FLOAT,0,pointsF);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
float pointsG[4][2] = {{texof-iff,of},{texof-iff,texof},{texof,of},{texof,texof}};
glVertexPointer(2,GL_FLOAT,0,pointsG);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
float pointsH[4][2] = {{of+iff,texof},{of+iff,texof-iff},{texof-iff,texof},{texof-iff,texof-iff}};
glVertexPointer(2,GL_FLOAT,0,pointsH);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
}

View File

@ -0,0 +1,135 @@
#ifndef Renderable_HPP
#define Renderable_HPP
#include <vector>
#include <typeinfo>
#include "TextureManager.hpp"
class BeatDetect;
class RenderContext
{
public:
float time;
int texsize;
float aspectRatio;
bool aspectCorrect;
BeatDetect *beatDetect;
TextureManager *textureManager;
RenderContext();
};
class RenderItem
{
public:
float masterAlpha;
virtual void Draw(RenderContext &context) = 0;
RenderItem();
};
typedef std::vector<RenderItem*> RenderItemList;
class DarkenCenter : public RenderItem
{
public:
DarkenCenter();
void Draw(RenderContext &context);
};
class Shape : public RenderItem
{
public:
std::string imageUrl;
int sides;
bool thickOutline;
bool enabled;
bool additive;
bool textured;
float tex_zoom;
float tex_ang;
float x; /* x position */
float y; /* y position */
float radius;
float ang;
float r; /* red color value */
float g; /* green color value */
float b; /* blue color value */
float a; /* alpha color value */
float r2; /* red color value */
float g2; /* green color value */
float b2; /* blue color value */
float a2; /* alpha color value */
float border_r; /* red color value */
float border_g; /* green color value */
float border_b; /* blue color value */
float border_a; /* alpha color value */
Shape();
virtual void Draw(RenderContext &context);
};
class Text : RenderItem
{
};
class MotionVectors : public RenderItem
{
public:
float r;
float g;
float b;
float a;
float length;
float x_num;
float y_num;
float x_offset;
float y_offset;
void Draw(RenderContext &context);
MotionVectors();
};
class Border : public RenderItem
{
public:
float outer_size;
float outer_r;
float outer_g;
float outer_b;
float outer_a;
float inner_size;
float inner_r;
float inner_g;
float inner_b;
float inner_a;
void Draw(RenderContext &context);
Border();
};
struct TypeIdPair {
TypeIdPair(const std::type_info & info1, const std::type_info & info2): id1(info1.name()), id2(info2.name()) {}
TypeIdPair(const std::string & id1, const std::string & id2): id1(id1), id2(id2) {}
std::string id1;
std::string id2;
inline bool operator<(const TypeIdPair & rhs) const {
return this->id1 < rhs.id1 || (this->id1 == rhs.id1 && this->id2 < rhs.id2);
}
inline bool operator>(const TypeIdPair & rhs) const {
return !operator<(rhs) && !operator==(rhs);
}
inline bool operator==(const TypeIdPair & rhs) const {
return this->id1 == rhs.id1 && this->id2 == rhs.id2;
}
};
#endif

View File

@ -0,0 +1,774 @@
#include "Renderer.hpp"
#include "wipemalloc.h"
#include "math.h"
#include "Common.hpp"
#include "KeyHandler.hpp"
#include "TextureManager.hpp"
#include <iostream>
#include <algorithm>
#include <cassert>
#include "omptl/omptl"
#include "omptl/omptl_algorithm"
#include "UserTexture.hpp"
class Preset;
Renderer::Renderer(int width, int height, int gx, int gy, int texsize, BeatDetect *beatDetect, std::string _presetURL,
std::string _titlefontURL, std::string _menufontURL) :
title_fontURL(_titlefontURL), menu_fontURL(_menufontURL), presetURL(_presetURL), m_presetName("None"), vw(width),
vh(height), texsize(texsize), mesh(gx, gy)
{
int x;
int y;
this->totalframes = 1;
this->noSwitch = false;
this->showfps = false;
this->showtitle = false;
this->showpreset = false;
this->showhelp = false;
this->showstats = false;
this->studio = false;
this->realfps = 0;
this->drawtitle = 0;
//this->title = "Unknown";
/** Other stuff... */
this->correction = true;
this->aspect = (float) height / (float) width;;
/// @bug put these on member init list
this->renderTarget = new RenderTarget(texsize, width, height);
this->textureManager = new TextureManager(presetURL);
this->beatDetect = beatDetect;
#ifdef USE_FTGL
/**f Load the standard fonts */
title_font = new FTGLPixmapFont(title_fontURL.c_str());
other_font = new FTGLPixmapFont(menu_fontURL.c_str());
other_font->UseDisplayList(true);
title_font->UseDisplayList(true);
poly_font = new FTGLExtrdFont(title_fontURL.c_str());
poly_font->UseDisplayList(true);
poly_font->Depth(20);
poly_font->FaceSize(72);
poly_font->UseDisplayList(true);
#endif /** USE_FTGL */
int size = (mesh.height - 1) *mesh.width * 5 * 2;
p = ( float * ) wipemalloc ( size * sizeof ( float ) );
for (int j = 0; j < mesh.height - 1; j++)
{
int base = j * mesh.width * 2 * 5;
for (int i = 0; i < mesh.width; i++)
{
int index = j * mesh.width + i;
int index2 = (j + 1) * mesh.width + i;
int strip = base + i * 10;
p[strip + 2] = mesh.identity[index].x;
p[strip + 3] = mesh.identity[index].y;
p[strip + 4] = 0;
p[strip + 7] = mesh.identity[index2].x;
p[strip + 8] = mesh.identity[index2].y;
p[strip + 9] = 0;
}
}
#ifdef USE_CG
shaderEngine.setParams(renderTarget->texsize, renderTarget->textureID[1], aspect, beatDetect, textureManager);
#endif
}
void Renderer::SetPipeline(Pipeline &pipeline)
{
currentPipe = &pipeline;
#ifdef USE_CG
shaderEngine.reset();
shaderEngine.loadShader(pipeline.warpShader);
shaderEngine.loadShader(pipeline.compositeShader);
#endif
}
void Renderer::ResetTextures()
{
textureManager->Clear();
delete (renderTarget);
renderTarget = new RenderTarget(texsize, vw, vh);
reset(vw, vh);
textureManager->Preload();
}
void Renderer::SetupPass1(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
//glMatrixMode(GL_PROJECTION);
//glPushMatrix();
//glMatrixMode(GL_MODELVIEW);
//glPushMatrix();
totalframes++;
renderTarget->lock();
glViewport(0, 0, renderTarget->texsize, renderTarget->texsize);
glEnable(GL_TEXTURE_2D);
//If using FBO, switch to FBO texture
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#ifdef USE_GLES1
glOrthof(0.0, 1, 0.0, 1, -40, 40);
#else
glOrtho(0.0, 1, 0.0, 1, -40, 40);
#endif
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#ifdef USE_CG
shaderEngine.RenderBlurTextures(pipeline, pipelineContext, renderTarget->texsize);
#endif
}
void Renderer::RenderItems(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
renderContext.time = pipelineContext.time;
renderContext.texsize = texsize;
renderContext.aspectCorrect = correction;
renderContext.aspectRatio = aspect;
renderContext.textureManager = textureManager;
renderContext.beatDetect = beatDetect;
for (std::vector<RenderItem*>::const_iterator pos = pipeline.drawables.begin(); pos != pipeline.drawables.end(); ++pos)
{
if (*pos != NULL)
{
(*pos)->Draw(renderContext);
}
}
}
void Renderer::FinishPass1()
{
draw_title_to_texture();
/** Restore original view state */
//glMatrixMode(GL_MODELVIEW);
//glPopMatrix();
//glMatrixMode(GL_PROJECTION);
//glPopMatrix();
renderTarget->unlock();
}
void Renderer::Pass2(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
//BEGIN PASS 2
//
//end of texture rendering
//now we copy the texture from the FBO or framebuffer to
//video texture memory and render fullscreen.
/** Reset the viewport size */
#ifdef USE_FBO
if (renderTarget->renderToTexture)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->renderTarget->fbuffer[1]);
glViewport(0, 0, this->renderTarget->texsize, this->renderTarget->texsize);
}
else
#endif
glViewport(0, 0, this->vw, this->vh);
glBindTexture(GL_TEXTURE_2D, this->renderTarget->textureID[0]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#ifdef USE_GLES1
glOrthof(-0.5, 0.5, -0.5, 0.5, -40, 40);
#else
glOrtho(-0.5, 0.5, -0.5, 0.5, -40, 40);
#endif
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLineWidth(this->renderTarget->texsize < 512 ? 1 : this->renderTarget->texsize / 512.0);
CompositeOutput(pipeline, pipelineContext);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-0.5, -0.5, 0);
// When console refreshes, there is a chance the preset has been changed by the user
refreshConsole();
draw_title_to_screen(false);
if (this->showhelp % 2)
draw_help();
if (this->showtitle % 2)
draw_title();
if (this->showfps % 2)
draw_fps(this->realfps);
if (this->showpreset % 2)
draw_preset();
if (this->showstats % 2)
draw_stats();
glTranslatef(0.5, 0.5, 0);
#ifdef USE_FBO
if (renderTarget->renderToTexture)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
#endif
}
void Renderer::RenderFrame(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
SetupPass1(pipeline, pipelineContext);
#ifdef USE_CG
shaderEngine.enableShader(currentPipe->warpShader, pipeline, pipelineContext);
#endif
Interpolation(pipeline);
#ifdef USE_CG
shaderEngine.disableShader();
#endif
RenderItems(pipeline, pipelineContext);
FinishPass1();
Pass2(pipeline, pipelineContext);
}
void Renderer::Interpolation(const Pipeline &pipeline)
{
if (this->renderTarget->useFBO)
glBindTexture(GL_TEXTURE_2D, renderTarget->textureID[1]);
else
glBindTexture(GL_TEXTURE_2D, renderTarget->textureID[0]);
//Texture wrapping( clamp vs. wrap)
if (pipeline.textureWrap == 0)
{
#ifdef USE_GLES1
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#else
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
#endif
}
else
{
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
glColor4f(1.0, 1.0, 1.0, pipeline.screenDecay);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
//glVertexPointer(2, GL_FLOAT, 0, p);
//glTexCoordPointer(2, GL_FLOAT, 0, t);
glInterleavedArrays(GL_T2F_V3F,0,p);
if (pipeline.staticPerPixel)
{
for (int j = 0; j < mesh.height - 1; j++)
{
int base = j * mesh.width * 2 * 5;
for (int i = 0; i < mesh.width; i++)
{
int strip = base + i * 10;
p[strip] = pipeline.x_mesh[i][j];
p[strip + 1] = pipeline.y_mesh[i][j];
p[strip + 5] = pipeline.x_mesh[i][j+1];
p[strip + 6] = pipeline.y_mesh[i][j+1];
}
}
}
else
{
mesh.Reset();
omptl::transform(mesh.p.begin(), mesh.p.end(), mesh.identity.begin(), mesh.p.begin(), &Renderer::PerPixel);
for (int j = 0; j < mesh.height - 1; j++)
{
int base = j * mesh.width * 2 * 5;
for (int i = 0; i < mesh.width; i++)
{
int strip = base + i * 10;
int index = j * mesh.width + i;
int index2 = (j + 1) * mesh.width + i;
p[strip] = mesh.p[index].x;
p[strip + 1] = mesh.p[index].y;
p[strip + 5] = mesh.p[index2].x;
p[strip + 6] = mesh.p[index2].y;
}
}
}
for (int j = 0; j < mesh.height - 1; j++)
glDrawArrays(GL_TRIANGLE_STRIP,j* mesh.width* 2,mesh.width*2);
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Pipeline* Renderer::currentPipe;
Renderer::~Renderer()
{
int x;
if (renderTarget)
delete (renderTarget);
if (textureManager)
delete (textureManager);
//std::cerr << "grid assign end" << std::endl;
free(p);
#ifdef USE_FTGL
// std::cerr << "freeing title fonts" << std::endl;
if (title_font)
delete title_font;
if (poly_font)
delete poly_font;
if (other_font)
delete other_font;
// std::cerr << "freeing title fonts finished" << std::endl;
#endif
// std::cerr << "exiting destructor" << std::endl;
}
void Renderer::reset(int w, int h)
{
aspect = (float) h / (float) w;
this -> vw = w;
this -> vh = h;
#if USE_CG
shaderEngine.setAspect(aspect);
#endif
glShadeModel(GL_SMOOTH);
glCullFace(GL_BACK);
//glFrontFace( GL_CCW );
glClearColor(0, 0, 0, 0);
glViewport(0, 0, w, h);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
#ifndef USE_GLES1
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
#endif
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glClear(GL_COLOR_BUFFER_BIT);
#ifndef USE_GLES1
glLineStipple(2, 0xAAAA);
#endif
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
//glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
if (!this->renderTarget->useFBO)
{
this->renderTarget->fallbackRescale(w, h);
}
}
GLuint Renderer::initRenderToTexture()
{
return renderTarget->initRenderToTexture();
}
void Renderer::draw_title_to_texture()
{
#ifdef USE_FTGL
if (this->drawtitle > 100)
{
draw_title_to_screen(true);
this->drawtitle = 0;
}
#endif /** USE_FTGL */
}
float title_y;
void Renderer::draw_title_to_screen(bool flip)
{
#ifdef USE_FTGL
if (this->drawtitle > 0)
{
//setUpLighting();
//glEnable(GL_POLYGON_SMOOTH);
//glEnable( GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT);
int draw;
if (drawtitle >= 80)
draw = 80;
else
draw = drawtitle;
float easein = ((80 - draw) * .0125);
float easein2 = easein * easein;
if (drawtitle == 1)
{
title_y = (float) rand() / RAND_MAX;
title_y *= 2;
title_y -= 1;
title_y *= .6;
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glBlendFunc(GL_SRC_ALPHA_SATURATE,GL_ONE);
glColor4f(1.0, 1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glFrustum(-1, 1, -1 * (float) vh / (float) vw, 1 * (float) vh / (float) vw, 1, 1000);
if (flip)
glScalef(1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glTranslatef(-850, title_y * 850 * vh / vw, easein2 * 900 - 900);
glRotatef(easein2 * 360, 1, 0, 0);
poly_font->Render(this->title.c_str());
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
this->drawtitle++;
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LIGHTING);
glDisable(GL_POLYGON_SMOOTH);
}
#endif /** USE_FTGL */
}
void Renderer::draw_title()
{
#ifdef USE_FTGL
//glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
glColor4f(1.0, 1.0, 1.0, 1.0);
// glPushMatrix();
// glTranslatef(this->vw*.001,this->vh*.03, -1);
// glScalef(this->vw*.015,this->vh*.025,0);
glRasterPos2f(0.01, 0.05);
title_font->FaceSize((unsigned) (20 * (this->vh / 512.0)));
title_font->Render(this->title.c_str());
// glPopMatrix();
//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
#endif /** USE_FTGL */
}
void Renderer::draw_preset()
{
#ifdef USE_FTGL
//glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
glColor4f(1.0, 1.0, 1.0, 1.0);
// glPushMatrix();
//glTranslatef(this->vw*.001,this->vh*-.01, -1);
//glScalef(this->vw*.003,this->vh*.004,0);
glRasterPos2f(0.01, 0.01);
title_font->FaceSize((unsigned) (12 * (this->vh / 512.0)));
if (this->noSwitch)
title_font->Render("[LOCKED] ");
title_font->FaceSize((unsigned) (20 * (this->vh / 512.0)));
title_font->Render(this->presetName().c_str());
//glPopMatrix();
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
#endif /** USE_FTGL */
}
void Renderer::draw_help()
{
#ifdef USE_FTGL
//glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
glColor4f(1.0, 1.0, 1.0, 1.0);
glPushMatrix();
glTranslatef(0, 1, 0);
//glScalef(this->vw*.02,this->vh*.02 ,0);
title_font->FaceSize((unsigned) (18 * (this->vh / 512.0)));
glRasterPos2f(0.01, -0.05);
title_font->Render("Help");
glRasterPos2f(0.01, -0.09);
title_font->Render("----------------------------");
glRasterPos2f(0.01, -0.13);
title_font->Render("F1: This help menu");
glRasterPos2f(0.01, -0.17);
title_font->Render("F2: Show song title");
glRasterPos2f(0.01, -0.21);
title_font->Render("F3: Show preset name");
glRasterPos2f(0.01, -0.25);
title_font->Render("F4: Show Rendering Settings");
glRasterPos2f(0.01, -0.29);
title_font->Render("F5: Show FPS");
glRasterPos2f(0.01, -0.35);
title_font->Render("F: Fullscreen");
glRasterPos2f(0.01, -0.39);
title_font->Render("L: Lock/Unlock Preset");
glRasterPos2f(0.01, -0.43);
title_font->Render("M: Show Menu");
glRasterPos2f(0.01, -0.49);
title_font->Render("R: Random preset");
glRasterPos2f(0.01, -0.53);
title_font->Render("N: Next preset");
glRasterPos2f(0.01, -0.57);
title_font->Render("P: Previous preset");
glPopMatrix();
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
#endif /** USE_FTGL */
}
void Renderer::draw_stats()
{
#ifdef USE_FTGL
char buffer[128];
float offset = (this->showfps % 2 ? -0.05 : 0.0);
// glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
glColor4f(1.0, 1.0, 1.0, 1.0);
glPushMatrix();
glTranslatef(0.01, 1, 0);
glRasterPos2f(0, -.05 + offset);
other_font->Render(this->correction ? " aspect: corrected" : " aspect: stretched");
sprintf(buffer, " (%f)", this->aspect);
other_font->Render(buffer);
glRasterPos2f(0, -.09 + offset);
other_font->FaceSize((unsigned) (18 * (vh / 512.0)));
sprintf(buffer, " texsize: %d", renderTarget->texsize);
other_font->Render(buffer);
glRasterPos2f(0, -.13 + offset);
sprintf(buffer, " viewport: %d x %d", vw, vh);
other_font->Render(buffer);
glRasterPos2f(0, -.17 + offset);
other_font->Render((renderTarget->useFBO ? " FBO: on" : " FBO: off"));
glRasterPos2f(0, -.21 + offset);
sprintf(buffer, " mesh: %d x %d", mesh.width, mesh.height);
other_font->Render(buffer);
glRasterPos2f(0, -.25 + offset);
sprintf(buffer, " textures: %.1fkB", textureManager->getTextureMemorySize() / 1000.0f);
other_font->Render(buffer);
#ifdef USE_CG
glRasterPos2f(0, -.29 + offset);
sprintf(buffer, "shader profile: %s", shaderEngine.profileName.c_str());
other_font->Render(buffer);
glRasterPos2f(0, -.33 + offset);
sprintf(buffer, " warp shader: %s", currentPipe->warpShader.enabled ? "on" : "off");
other_font->Render(buffer);
glRasterPos2f(0, -.37 + offset);
sprintf(buffer, " comp shader: %s", currentPipe->compositeShader.enabled ? "on" : "off");
other_font->Render(buffer);
#endif
glPopMatrix();
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
#endif /** USE_FTGL */
}
void Renderer::draw_fps(float realfps)
{
#ifdef USE_FTGL
char bufferfps[20];
sprintf(bufferfps, "%.1f fps", realfps);
// glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
glColor4f(1.0, 1.0, 1.0, 1.0);
glPushMatrix();
glTranslatef(0.01, 1, 0);
glRasterPos2f(0, -0.05);
title_font->FaceSize((unsigned) (20 * (this->vh / 512.0)));
title_font->Render(bufferfps);
glPopMatrix();
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
#endif /** USE_FTGL */
}
void Renderer::CompositeOutput(const Pipeline &pipeline, const PipelineContext &pipelineContext)
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Overwrite anything on the screen
glBlendFunc(GL_ONE, GL_ZERO);
glColor4f(1.0, 1.0, 1.0, 1.0f);
glEnable(GL_TEXTURE_2D);
#ifdef USE_CG
shaderEngine.enableShader(currentPipe->compositeShader, pipeline, pipelineContext);
#endif
float tex[4][2] =
{
{ 0, 1 },
{ 0, 0 },
{ 1, 0 },
{ 1, 1 } };
float points[4][2] =
{
{ -0.5, -0.5 },
{ -0.5, 0.5 },
{ 0.5, 0.5 },
{ 0.5, -0.5 } };
glEnableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, points);
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#ifdef USE_CG
shaderEngine.disableShader();
#endif
for (std::vector<RenderItem*>::const_iterator pos = pipeline.compositeDrawables.begin(); pos
!= pipeline.compositeDrawables.end(); ++pos)
(*pos)->Draw(renderContext);
}

View File

@ -0,0 +1,145 @@
#ifndef Renderer_HPP
#define Renderer_HPP
#include "FBO.hpp"
#include "BeatDetect.hpp"
#include "Common.hpp"
#include <string>
#include <set>
#ifdef USE_GLES1
#include <GLES/gl.h>
#else
#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#endif
#ifdef USE_FTGL
#ifdef WIN32
#include <ftgl.h>
#include <FTGLPixmapFont.h>
#include <FTGLExtrdFont.h>
#else
#include <FTGL/FTFont.h>
#include <FTGL/FTGLPixmapFont.h>
#include <FTGL/FTGLExtrdFont.h>
#endif
#endif /** USE_FTGL */
#include "Pipeline.hpp"
#include "PerPixelMesh.hpp"
#include "Transformation.hpp"
#include "ShaderEngine.hpp"
class UserTexture;
class BeatDetect;
class TextureManager;
class Renderer
{
public:
bool showfps;
bool showtitle;
bool showpreset;
bool showhelp;
bool showstats;
bool studio;
bool correction;
bool noSwitch;
int totalframes;
float realfps;
std::string title;
int drawtitle;
int texsize;
Renderer( int width, int height, int gx, int gy, int texsize, BeatDetect *beatDetect, std::string presetURL, std::string title_fontURL, std::string menu_fontURL);
~Renderer();
void RenderFrame(const Pipeline &pipeline, const PipelineContext &pipelineContext);
void ResetTextures();
void reset(int w, int h);
GLuint initRenderToTexture();
void SetPipeline(Pipeline &pipeline);
void setPresetName(const std::string& theValue)
{
m_presetName = theValue;
}
std::string presetName() const
{
return m_presetName;
}
private:
PerPixelMesh mesh;
RenderTarget *renderTarget;
BeatDetect *beatDetect;
TextureManager *textureManager;
static Pipeline* currentPipe;
RenderContext renderContext;
//per pixel equation variables
#ifdef USE_CG
ShaderEngine shaderEngine;
#endif
std::string m_presetName;
float* p;
int vw;
int vh;
float aspect;
std::string title_fontURL;
std::string menu_fontURL;
std::string presetURL;
#ifdef USE_FTGL
FTGLPixmapFont *title_font;
FTGLPixmapFont *other_font;
FTGLExtrdFont *poly_font;
#endif /** USE_FTGL */
void SetupPass1(const Pipeline &pipeline, const PipelineContext &pipelineContext);
void Interpolation(const Pipeline &pipeline);
void RenderItems(const Pipeline &pipeline, const PipelineContext &pipelineContext);
void FinishPass1();
void Pass2 (const Pipeline &pipeline, const PipelineContext &pipelineContext);
void CompositeOutput(const Pipeline &pipeline, const PipelineContext &pipelineContext);
inline static Point PerPixel(Point p, PerPixelContext &context)
{
return currentPipe->PerPixel(p,context);
}
void rescale_per_pixel_matrices();
void draw_fps( float realfps );
void draw_stats();
void draw_help();
void draw_preset();
void draw_title();
void draw_title_to_screen(bool flip);
void draw_title_to_texture();
};
#endif

2040
3rdparty/libprojectm/Renderer/SOIL/SOIL.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,444 @@
/**
@mainpage SOIL
Jonathan Dummer
2007-07-26-10.36
Simple OpenGL Image Library
A tiny c library for uploading images as
textures into OpenGL. Also saving and
loading of images is supported.
I'm using Sean's Tool Box image loader as a base:
http://www.nothings.org/
I'm upgrading it to load TGA and DDS files, and a direct
path for loading DDS files straight into OpenGL textures,
when applicable.
Image Formats:
- BMP load & save
- TGA load & save
- DDS load & save
- PNG load
- JPG load
OpenGL Texture Features:
- resample to power-of-two sizes
- MIPmap generation
- compressed texture S3TC formats (if supported)
- can pre-multiply alpha for you, for better compositing
- can flip image about the y-axis (except pre-compressed DDS files)
Thanks to:
* Sean Barret - for the awesome stb_image
* Dan Venkitachalam - for finding some non-compliant DDS files, and patching some explicit casts
* everybody at gamedev.net
**/
#ifndef HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY
#define HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY
#ifdef __cplusplus
extern "C" {
#endif
/**
The format of images that may be loaded (force_channels).
SOIL_LOAD_AUTO leaves the image in whatever format it was found.
SOIL_LOAD_L forces the image to load as Luminous (greyscale)
SOIL_LOAD_LA forces the image to load as Luminous with Alpha
SOIL_LOAD_RGB forces the image to load as Red Green Blue
SOIL_LOAD_RGBA forces the image to load as Red Green Blue Alpha
**/
enum
{
SOIL_LOAD_AUTO = 0,
SOIL_LOAD_L = 1,
SOIL_LOAD_LA = 2,
SOIL_LOAD_RGB = 3,
SOIL_LOAD_RGBA = 4
};
/**
Passed in as reuse_texture_ID, will cause SOIL to
register a new texture ID using glGenTextures().
If the value passed into reuse_texture_ID > 0 then
SOIL will just re-use that texture ID (great for
reloading image assets in-game!)
**/
enum
{
SOIL_CREATE_NEW_ID = 0
};
/**
flags you can pass into SOIL_load_OGL_texture()
and SOIL_create_OGL_texture().
(note that if SOIL_FLAG_DDS_LOAD_DIRECT is used
the rest of the flags with the exception of
SOIL_FLAG_TEXTURE_REPEATS will be ignored while
loading already-compressed DDS files.)
SOIL_FLAG_POWER_OF_TWO: force the image to be POT
SOIL_FLAG_MIPMAPS: generate mipmaps for the texture
SOIL_FLAG_TEXTURE_REPEATS: otherwise will clamp
SOIL_FLAG_MULTIPLY_ALPHA: for using (GL_ONE,GL_ONE_MINUS_SRC_ALPHA) blending
SOIL_FLAG_INVERT_Y: flip the image vertically
SOIL_FLAG_COMPRESS_TO_DXT: if the card can display them, will convert RGB to DXT1, RGBA to DXT5
SOIL_FLAG_DDS_LOAD_DIRECT: will load DDS files directly without _ANY_ additional processing
SOIL_FLAG_NTSC_SAFE_RGB: clamps RGB components to the range [16,235]
SOIL_FLAG_CoCg_Y: Google YCoCg; RGB=>CoYCg, RGBA=>CoCgAY
SOIL_FLAG_TEXTURE_RECTANGE: uses ARB_texture_rectangle ; pixel indexed & no repeat or MIPmaps or cubemaps
**/
enum
{
SOIL_FLAG_POWER_OF_TWO = 1,
SOIL_FLAG_MIPMAPS = 2,
SOIL_FLAG_TEXTURE_REPEATS = 4,
SOIL_FLAG_MULTIPLY_ALPHA = 8,
SOIL_FLAG_INVERT_Y = 16,
SOIL_FLAG_COMPRESS_TO_DXT = 32,
SOIL_FLAG_DDS_LOAD_DIRECT = 64,
SOIL_FLAG_NTSC_SAFE_RGB = 128,
SOIL_FLAG_CoCg_Y = 256,
SOIL_FLAG_TEXTURE_RECTANGLE = 512
};
/**
The types of images that may be saved.
(TGA supports uncompressed RGB / RGBA)
(BMP supports uncompressed RGB)
(DDS supports DXT1 and DXT5)
**/
enum
{
SOIL_SAVE_TYPE_TGA = 0,
SOIL_SAVE_TYPE_BMP = 1,
SOIL_SAVE_TYPE_DDS = 2
};
/**
Defines the order of faces in a DDS cubemap.
I recommend that you use the same order in single
image cubemap files, so they will be interchangeable
with DDS cubemaps when using SOIL.
**/
#define SOIL_DDS_CUBEMAP_FACE_ORDER "EWUDNS"
/**
The types of internal fake HDR representations
SOIL_HDR_RGBE: RGB * pow( 2.0, A - 128.0 )
SOIL_HDR_RGBdivA: RGB / A
SOIL_HDR_RGBdivA2: RGB / (A*A)
**/
enum
{
SOIL_HDR_RGBE = 0,
SOIL_HDR_RGBdivA = 1,
SOIL_HDR_RGBdivA2 = 2
};
/**
Loads an image from disk into an OpenGL texture.
\param filename the name of the file to upload as a texture
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_load_OGL_texture
(
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
unsigned int
SOIL_load_OGL_texture_size
(
const char *filename,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags,
int *width,
int *height
);
/**
Loads 6 images from disk into an OpenGL cubemap texture.
\param x_pos_file the name of the file to upload as the +x cube face
\param x_neg_file the name of the file to upload as the -x cube face
\param y_pos_file the name of the file to upload as the +y cube face
\param y_neg_file the name of the file to upload as the -y cube face
\param z_pos_file the name of the file to upload as the +z cube face
\param z_neg_file the name of the file to upload as the -z cube face
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_load_OGL_cubemap
(
const char *x_pos_file,
const char *x_neg_file,
const char *y_pos_file,
const char *y_neg_file,
const char *z_pos_file,
const char *z_neg_file,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Loads 1 image from disk and splits it into an OpenGL cubemap texture.
\param filename the name of the file to upload as a texture
\param face_order the order of the faces in the file, any combination of NSWEUD, for North, South, Up, etc.
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_load_OGL_single_cubemap
(
const char *filename,
const char face_order[6],
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Loads an HDR image from disk into an OpenGL texture.
\param filename the name of the file to upload as a texture
\param fake_HDR_format SOIL_HDR_RGBE, SOIL_HDR_RGBdivA, SOIL_HDR_RGBdivA2
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_load_OGL_HDR_texture
(
const char *filename,
int fake_HDR_format,
int rescale_to_max,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Loads an image from RAM into an OpenGL texture.
\param buffer the image data in RAM just as if it were still in a file
\param buffer_length the size of the buffer in bytes
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_load_OGL_texture_from_memory
(
const unsigned char *const buffer,
int buffer_length,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Loads 6 images from memory into an OpenGL cubemap texture.
\param x_pos_buffer the image data in RAM to upload as the +x cube face
\param x_pos_buffer_length the size of the above buffer
\param x_neg_buffer the image data in RAM to upload as the +x cube face
\param x_neg_buffer_length the size of the above buffer
\param y_pos_buffer the image data in RAM to upload as the +x cube face
\param y_pos_buffer_length the size of the above buffer
\param y_neg_buffer the image data in RAM to upload as the +x cube face
\param y_neg_buffer_length the size of the above buffer
\param z_pos_buffer the image data in RAM to upload as the +x cube face
\param z_pos_buffer_length the size of the above buffer
\param z_neg_buffer the image data in RAM to upload as the +x cube face
\param z_neg_buffer_length the size of the above buffer
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_load_OGL_cubemap_from_memory
(
const unsigned char *const x_pos_buffer,
int x_pos_buffer_length,
const unsigned char *const x_neg_buffer,
int x_neg_buffer_length,
const unsigned char *const y_pos_buffer,
int y_pos_buffer_length,
const unsigned char *const y_neg_buffer,
int y_neg_buffer_length,
const unsigned char *const z_pos_buffer,
int z_pos_buffer_length,
const unsigned char *const z_neg_buffer,
int z_neg_buffer_length,
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Loads 1 image from RAM and splits it into an OpenGL cubemap texture.
\param buffer the image data in RAM just as if it were still in a file
\param buffer_length the size of the buffer in bytes
\param face_order the order of the faces in the file, any combination of NSWEUD, for North, South, Up, etc.
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_load_OGL_single_cubemap_from_memory
(
const unsigned char *const buffer,
int buffer_length,
const char face_order[6],
int force_channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Creates a 2D OpenGL texture from raw image data. Note that the raw data is
_NOT_ freed after the upload (so the user can load various versions).
\param data the raw data to be uploaded as an OpenGL texture
\param width the width of the image in pixels
\param height the height of the image in pixels
\param channels the number of channels: 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_create_OGL_texture
(
const unsigned char *const data,
int width, int height, int channels,
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Creates an OpenGL cubemap texture by splitting up 1 image into 6 parts.
\param data the raw data to be uploaded as an OpenGL texture
\param width the width of the image in pixels
\param height the height of the image in pixels
\param channels the number of channels: 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
\param face_order the order of the faces in the file, and combination of NSWEUD, for North, South, Up, etc.
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
\return 0-failed, otherwise returns the OpenGL texture handle
**/
unsigned int
SOIL_create_OGL_single_cubemap
(
const unsigned char *const data,
int width, int height, int channels,
const char face_order[6],
unsigned int reuse_texture_ID,
unsigned int flags
);
/**
Captures the OpenGL window (RGB) and saves it to disk
\return 0 if it failed, otherwise returns 1
**/
int
SOIL_save_screenshot
(
const char *filename,
int image_type,
int x, int y,
int width, int height
);
/**
Loads an image from disk into an array of unsigned chars.
Note that *channels return the original channel count of the
image. If force_channels was other than SOIL_LOAD_AUTO,
the resulting image has force_channels, but *channels may be
different (if the original image had a different channel
count).
\return 0 if failed, otherwise returns 1
**/
unsigned char*
SOIL_load_image
(
const char *filename,
int *width, int *height, int *channels,
int force_channels
);
/**
Loads an image from memory into an array of unsigned chars.
Note that *channels return the original channel count of the
image. If force_channels was other than SOIL_LOAD_AUTO,
the resulting image has force_channels, but *channels may be
different (if the original image had a different channel
count).
\return 0 if failed, otherwise returns 1
**/
unsigned char*
SOIL_load_image_from_memory
(
const unsigned char *const buffer,
int buffer_length,
int *width, int *height, int *channels,
int force_channels
);
/**
Saves an image from an array of unsigned chars (RGBA) to disk
\return 0 if failed, otherwise returns 1
**/
int
SOIL_save_image
(
const char *filename,
int image_type,
int width, int height, int channels,
const unsigned char *const data
);
/**
Frees the image data (note, this is just C's "free()"...this function is
present mostly so C++ programmers don't forget to use "free()" and call
"delete []" instead [8^)
**/
void
SOIL_free_image_data
(
unsigned char *img_data
);
/**
This function resturn a pointer to a string describing the last thing
that happened inside SOIL. It can be used to determine why an image
failed to load.
**/
const char*
SOIL_last_result
(
void
);
#ifdef __cplusplus
}
#endif
#endif /* HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY */

View File

@ -0,0 +1,632 @@
/*
Jonathan Dummer
2007-07-31-10.32
simple DXT compression / decompression code
public domain
*/
#include "image_DXT.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/* set this =1 if you want to use the covarince matrix method...
which is better than my method of using standard deviations
overall, except on the infintesimal chance that the power
method fails for finding the largest eigenvector */
#define USE_COV_MAT 1
/********* Function Prototypes *********/
/*
Takes a 4x4 block of pixels and compresses it into 8 bytes
in DXT1 format (color only, no alpha). Speed is valued
over prettyness, at least for now.
*/
void compress_DDS_color_block(
int channels,
const unsigned char *const uncompressed,
unsigned char compressed[8] );
/*
Takes a 4x4 block of pixels and compresses the alpha
component it into 8 bytes for use in DXT5 DDS files.
Speed is valued over prettyness, at least for now.
*/
void compress_DDS_alpha_block(
const unsigned char *const uncompressed,
unsigned char compressed[8] );
/********* Actual Exposed Functions *********/
int
save_image_as_DDS
(
const char *filename,
int width, int height, int channels,
const unsigned char *const data
)
{
/* variables */
FILE *fout;
unsigned char *DDS_data;
DDS_header header;
int DDS_size;
/* error check */
if( (NULL == filename) ||
(width < 1) || (height < 1) ||
(channels < 1) || (channels > 4) ||
(data == NULL ) )
{
return 0;
}
/* Convert the image */
if( (channels & 1) == 1 )
{
/* no alpha, just use DXT1 */
DDS_data = convert_image_to_DXT1( data, width, height, channels, &DDS_size );
} else
{
/* has alpha, so use DXT5 */
DDS_data = convert_image_to_DXT5( data, width, height, channels, &DDS_size );
}
/* save it */
memset( &header, 0, sizeof( DDS_header ) );
header.dwMagic = ('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24);
header.dwSize = 124;
header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_LINEARSIZE;
header.dwWidth = width;
header.dwHeight = height;
header.dwPitchOrLinearSize = DDS_size;
header.sPixelFormat.dwSize = 32;
header.sPixelFormat.dwFlags = DDPF_FOURCC;
if( (channels & 1) == 1 )
{
header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('1' << 24);
} else
{
header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('5' << 24);
}
header.sCaps.dwCaps1 = DDSCAPS_TEXTURE;
/* write it out */
fout = fopen( filename, "wb");
fwrite( &header, sizeof( DDS_header ), 1, fout );
fwrite( DDS_data, 1, DDS_size, fout );
fclose( fout );
/* done */
free( DDS_data );
return 1;
}
unsigned char* convert_image_to_DXT1(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size )
{
unsigned char *compressed;
int i, j, x, y;
unsigned char ublock[16*3];
unsigned char cblock[8];
int index = 0, chan_step = 1;
int block_count = 0;
/* error check */
*out_size = 0;
if( (width < 1) || (height < 1) ||
(NULL == uncompressed) ||
(channels < 1) || (channels > 4) )
{
return NULL;
}
/* for channels == 1 or 2, I do not step forward for R,G,B values */
if( channels < 3 )
{
chan_step = 0;
}
/* get the RAM for the compressed image
(8 bytes per 4x4 pixel block) */
*out_size = ((width+3) >> 2) * ((height+3) >> 2) * 8;
compressed = (unsigned char*)malloc( *out_size );
/* go through each block */
for( j = 0; j < height; j += 4 )
{
for( i = 0; i < width; i += 4 )
{
/* copy this block into a new one */
int idx = 0;
int mx = 4, my = 4;
if( j+4 >= height )
{
my = height - j;
}
if( i+4 >= width )
{
mx = width - i;
}
for( y = 0; y < my; ++y )
{
for( x = 0; x < mx; ++x )
{
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels];
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step];
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step];
}
for( x = mx; x < 4; ++x )
{
ublock[idx++] = ublock[0];
ublock[idx++] = ublock[1];
ublock[idx++] = ublock[2];
}
}
for( y = my; y < 4; ++y )
{
for( x = 0; x < 4; ++x )
{
ublock[idx++] = ublock[0];
ublock[idx++] = ublock[1];
ublock[idx++] = ublock[2];
}
}
/* compress the block */
++block_count;
compress_DDS_color_block( 3, ublock, cblock );
/* copy the data from the block into the main block */
for( x = 0; x < 8; ++x )
{
compressed[index++] = cblock[x];
}
}
}
return compressed;
}
unsigned char* convert_image_to_DXT5(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size )
{
unsigned char *compressed;
int i, j, x, y;
unsigned char ublock[16*4];
unsigned char cblock[8];
int index = 0, chan_step = 1;
int block_count = 0, has_alpha;
/* error check */
*out_size = 0;
if( (width < 1) || (height < 1) ||
(NULL == uncompressed) ||
(channels < 1) || ( channels > 4) )
{
return NULL;
}
/* for channels == 1 or 2, I do not step forward for R,G,B vales */
if( channels < 3 )
{
chan_step = 0;
}
/* # channels = 1 or 3 have no alpha, 2 & 4 do have alpha */
has_alpha = 1 - (channels & 1);
/* get the RAM for the compressed image
(16 bytes per 4x4 pixel block) */
*out_size = ((width+3) >> 2) * ((height+3) >> 2) * 16;
compressed = (unsigned char*)malloc( *out_size );
/* go through each block */
for( j = 0; j < height; j += 4 )
{
for( i = 0; i < width; i += 4 )
{
/* local variables, and my block counter */
int idx = 0;
int mx = 4, my = 4;
if( j+4 >= height )
{
my = height - j;
}
if( i+4 >= width )
{
mx = width - i;
}
for( y = 0; y < my; ++y )
{
for( x = 0; x < mx; ++x )
{
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels];
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step];
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step];
ublock[idx++] =
has_alpha * uncompressed[(j+y)*width*channels+(i+x)*channels+channels-1]
+ (1-has_alpha)*255;
}
for( x = mx; x < 4; ++x )
{
ublock[idx++] = ublock[0];
ublock[idx++] = ublock[1];
ublock[idx++] = ublock[2];
ublock[idx++] = ublock[3];
}
}
for( y = my; y < 4; ++y )
{
for( x = 0; x < 4; ++x )
{
ublock[idx++] = ublock[0];
ublock[idx++] = ublock[1];
ublock[idx++] = ublock[2];
ublock[idx++] = ublock[3];
}
}
/* now compress the alpha block */
compress_DDS_alpha_block( ublock, cblock );
/* copy the data from the compressed alpha block into the main buffer */
for( x = 0; x < 8; ++x )
{
compressed[index++] = cblock[x];
}
/* then compress the color block */
++block_count;
compress_DDS_color_block( 4, ublock, cblock );
/* copy the data from the compressed color block into the main buffer */
for( x = 0; x < 8; ++x )
{
compressed[index++] = cblock[x];
}
}
}
return compressed;
}
/********* Helper Functions *********/
int convert_bit_range( int c, int from_bits, int to_bits )
{
int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1);
return (b + (b >> from_bits)) >> from_bits;
}
int rgb_to_565( int r, int g, int b )
{
return
(convert_bit_range( r, 8, 5 ) << 11) |
(convert_bit_range( g, 8, 6 ) << 05) |
(convert_bit_range( b, 8, 5 ) << 00);
}
void rgb_888_from_565( unsigned int c, int *r, int *g, int *b )
{
*r = convert_bit_range( (c >> 11) & 31, 5, 8 );
*g = convert_bit_range( (c >> 05) & 63, 6, 8 );
*b = convert_bit_range( (c >> 00) & 31, 5, 8 );
}
void compute_color_line_STDEV(
const unsigned char *const uncompressed,
int channels,
float point[3], float direction[3] )
{
const float inv_16 = 1.0f / 16.0f;
int i;
float sum_r = 0.0f, sum_g = 0.0f, sum_b = 0.0f;
float sum_rr = 0.0f, sum_gg = 0.0f, sum_bb = 0.0f;
float sum_rg = 0.0f, sum_rb = 0.0f, sum_gb = 0.0f;
/* calculate all data needed for the covariance matrix
( to compare with _rygdxt code) */
for( i = 0; i < 16*channels; i += channels )
{
sum_r += uncompressed[i+0];
sum_rr += uncompressed[i+0] * uncompressed[i+0];
sum_g += uncompressed[i+1];
sum_gg += uncompressed[i+1] * uncompressed[i+1];
sum_b += uncompressed[i+2];
sum_bb += uncompressed[i+2] * uncompressed[i+2];
sum_rg += uncompressed[i+0] * uncompressed[i+1];
sum_rb += uncompressed[i+0] * uncompressed[i+2];
sum_gb += uncompressed[i+1] * uncompressed[i+2];
}
/* convert the sums to averages */
sum_r *= inv_16;
sum_g *= inv_16;
sum_b *= inv_16;
/* and convert the squares to the squares of the value - avg_value */
sum_rr -= 16.0f * sum_r * sum_r;
sum_gg -= 16.0f * sum_g * sum_g;
sum_bb -= 16.0f * sum_b * sum_b;
sum_rg -= 16.0f * sum_r * sum_g;
sum_rb -= 16.0f * sum_r * sum_b;
sum_gb -= 16.0f * sum_g * sum_b;
/* the point on the color line is the average */
point[0] = sum_r;
point[1] = sum_g;
point[2] = sum_b;
#if USE_COV_MAT
/*
The following idea was from ryg.
(https://mollyrocket.com/forums/viewtopic.php?t=392)
The method worked great (less RMSE than mine) most of
the time, but had some issues handling some simple
boundary cases, like full green next to full red,
which would generate a covariance matrix like this:
| 1 -1 0 |
| -1 1 0 |
| 0 0 0 |
For a given starting vector, the power method can
generate all zeros! So no starting with {1,1,1}
as I was doing! This kind of error is still a
slight posibillity, but will be very rare.
*/
/* use the covariance matrix directly
(1st iteration, don't use all 1.0 values!) */
sum_r = 1.0f;
sum_g = 2.718281828f;
sum_b = 3.141592654f;
direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
/* 2nd iteration, use results from the 1st guy */
sum_r = direction[0];
sum_g = direction[1];
sum_b = direction[2];
direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
/* 3rd iteration, use results from the 2nd guy */
sum_r = direction[0];
sum_g = direction[1];
sum_b = direction[2];
direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
#else
/* use my standard deviation method
(very robust, a tiny bit slower and less accurate) */
direction[0] = sqrt( sum_rr );
direction[1] = sqrt( sum_gg );
direction[2] = sqrt( sum_bb );
/* which has a greater component */
if( sum_gg > sum_rr )
{
/* green has greater component, so base the other signs off of green */
if( sum_rg < 0.0f )
{
direction[0] = -direction[0];
}
if( sum_gb < 0.0f )
{
direction[2] = -direction[2];
}
} else
{
/* red has a greater component */
if( sum_rg < 0.0f )
{
direction[1] = -direction[1];
}
if( sum_rb < 0.0f )
{
direction[2] = -direction[2];
}
}
#endif
}
void LSE_master_colors_max_min(
int *cmax, int *cmin,
int channels,
const unsigned char *const uncompressed )
{
int i, j;
/* the master colors */
int c0[3], c1[3];
/* used for fitting the line */
float sum_x[] = { 0.0f, 0.0f, 0.0f };
float sum_x2[] = { 0.0f, 0.0f, 0.0f };
float dot_max = 1.0f, dot_min = -1.0f;
float vec_len2 = 0.0f;
float dot;
/* error check */
if( (channels < 3) || (channels > 4) )
{
return;
}
compute_color_line_STDEV( uncompressed, channels, sum_x, sum_x2 );
vec_len2 = 1.0f / ( 0.00001f +
sum_x2[0]*sum_x2[0] + sum_x2[1]*sum_x2[1] + sum_x2[2]*sum_x2[2] );
/* finding the max and min vector values */
dot_max =
(
sum_x2[0] * uncompressed[0] +
sum_x2[1] * uncompressed[1] +
sum_x2[2] * uncompressed[2]
);
dot_min = dot_max;
for( i = 1; i < 16; ++i )
{
dot =
(
sum_x2[0] * uncompressed[i*channels+0] +
sum_x2[1] * uncompressed[i*channels+1] +
sum_x2[2] * uncompressed[i*channels+2]
);
if( dot < dot_min )
{
dot_min = dot;
} else if( dot > dot_max )
{
dot_max = dot;
}
}
/* and the offset (from the average location) */
dot = sum_x2[0]*sum_x[0] + sum_x2[1]*sum_x[1] + sum_x2[2]*sum_x[2];
dot_min -= dot;
dot_max -= dot;
/* post multiply by the scaling factor */
dot_min *= vec_len2;
dot_max *= vec_len2;
/* OK, build the master colors */
for( i = 0; i < 3; ++i )
{
/* color 0 */
c0[i] = (int)(0.5f + sum_x[i] + dot_max * sum_x2[i]);
if( c0[i] < 0 )
{
c0[i] = 0;
} else if( c0[i] > 255 )
{
c0[i] = 255;
}
/* color 1 */
c1[i] = (int)(0.5f + sum_x[i] + dot_min * sum_x2[i]);
if( c1[i] < 0 )
{
c1[i] = 0;
} else if( c1[i] > 255 )
{
c1[i] = 255;
}
}
/* down_sample (with rounding?) */
i = rgb_to_565( c0[0], c0[1], c0[2] );
j = rgb_to_565( c1[0], c1[1], c1[2] );
if( i > j )
{
*cmax = i;
*cmin = j;
} else
{
*cmax = j;
*cmin = i;
}
}
void
compress_DDS_color_block
(
int channels,
const unsigned char *const uncompressed,
unsigned char compressed[8]
)
{
/* variables */
int i;
int next_bit;
int enc_c0, enc_c1;
int c0[4], c1[4];
float color_line[] = { 0.0f, 0.0f, 0.0f, 0.0f };
float vec_len2 = 0.0f, dot_offset = 0.0f;
/* stupid order */
int swizzle4[] = { 0, 2, 3, 1 };
/* get the master colors */
LSE_master_colors_max_min( &enc_c0, &enc_c1, channels, uncompressed );
/* store the 565 color 0 and color 1 */
compressed[0] = (enc_c0 >> 0) & 255;
compressed[1] = (enc_c0 >> 8) & 255;
compressed[2] = (enc_c1 >> 0) & 255;
compressed[3] = (enc_c1 >> 8) & 255;
/* zero out the compressed data */
compressed[4] = 0;
compressed[5] = 0;
compressed[6] = 0;
compressed[7] = 0;
/* reconstitute the master color vectors */
rgb_888_from_565( enc_c0, &c0[0], &c0[1], &c0[2] );
rgb_888_from_565( enc_c1, &c1[0], &c1[1], &c1[2] );
/* the new vector */
vec_len2 = 0.0f;
for( i = 0; i < 3; ++i )
{
color_line[i] = (float)(c1[i] - c0[i]);
vec_len2 += color_line[i] * color_line[i];
}
if( vec_len2 > 0.0f )
{
vec_len2 = 1.0f / vec_len2;
}
/* pre-proform the scaling */
color_line[0] *= vec_len2;
color_line[1] *= vec_len2;
color_line[2] *= vec_len2;
/* compute the offset (constant) portion of the dot product */
dot_offset = color_line[0]*c0[0] + color_line[1]*c0[1] + color_line[2]*c0[2];
/* store the rest of the bits */
next_bit = 8*4;
for( i = 0; i < 16; ++i )
{
/* find the dot product of this color, to place it on the line
(should be [-1,1]) */
int next_value = 0;
float dot_product =
color_line[0] * uncompressed[i*channels+0] +
color_line[1] * uncompressed[i*channels+1] +
color_line[2] * uncompressed[i*channels+2] -
dot_offset;
/* map to [0,3] */
next_value = (int)( dot_product * 3.0f + 0.5f );
if( next_value > 3 )
{
next_value = 3;
} else if( next_value < 0 )
{
next_value = 0;
}
/* OK, store this value */
compressed[next_bit >> 3] |= swizzle4[ next_value ] << (next_bit & 7);
next_bit += 2;
}
/* done compressing to DXT1 */
}
void
compress_DDS_alpha_block
(
const unsigned char *const uncompressed,
unsigned char compressed[8]
)
{
/* variables */
int i;
int next_bit;
int a0, a1;
float scale_me;
/* stupid order */
int swizzle8[] = { 1, 7, 6, 5, 4, 3, 2, 0 };
/* get the alpha limits (a0 > a1) */
a0 = a1 = uncompressed[3];
for( i = 4+3; i < 16*4; i += 4 )
{
if( uncompressed[i] > a0 )
{
a0 = uncompressed[i];
} else if( uncompressed[i] < a1 )
{
a1 = uncompressed[i];
}
}
/* store those limits, and zero the rest of the compressed dataset */
compressed[0] = a0;
compressed[1] = a1;
/* zero out the compressed data */
compressed[2] = 0;
compressed[3] = 0;
compressed[4] = 0;
compressed[5] = 0;
compressed[6] = 0;
compressed[7] = 0;
/* store the all of the alpha values */
next_bit = 8*2;
scale_me = 7.9999f / (a0 - a1);
for( i = 3; i < 16*4; i += 4 )
{
/* convert this alpha value to a 3 bit number */
int svalue;
int value = (int)((uncompressed[i] - a1) * scale_me);
svalue = swizzle8[ value&7 ];
/* OK, store this value, start with the 1st byte */
compressed[next_bit >> 3] |= svalue << (next_bit & 7);
if( (next_bit & 7) > 5 )
{
/* spans 2 bytes, fill in the start of the 2nd byte */
compressed[1 + (next_bit >> 3)] |= svalue >> (8 - (next_bit & 7) );
}
next_bit += 3;
}
/* done compressing to DXT1 */
}

View File

@ -0,0 +1,123 @@
/*
Jonathan Dummer
2007-07-31-10.32
simple DXT compression / decompression code
public domain
*/
#ifndef HEADER_IMAGE_DXT
#define HEADER_IMAGE_DXT
/**
Converts an image from an array of unsigned chars (RGB or RGBA) to
DXT1 or DXT5, then saves the converted image to disk.
\return 0 if failed, otherwise returns 1
**/
int
save_image_as_DDS
(
const char *filename,
int width, int height, int channels,
const unsigned char *const data
);
/**
take an image and convert it to DXT1 (no alpha)
**/
unsigned char*
convert_image_to_DXT1
(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size
);
/**
take an image and convert it to DXT5 (with alpha)
**/
unsigned char*
convert_image_to_DXT5
(
const unsigned char *const uncompressed,
int width, int height, int channels,
int *out_size
);
/** A bunch of DirectDraw Surface structures and flags **/
typedef struct
{
unsigned int dwMagic;
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwHeight;
unsigned int dwWidth;
unsigned int dwPitchOrLinearSize;
unsigned int dwDepth;
unsigned int dwMipMapCount;
unsigned int dwReserved1[ 11 ];
/* DDPIXELFORMAT */
struct
{
unsigned int dwSize;
unsigned int dwFlags;
unsigned int dwFourCC;
unsigned int dwRGBBitCount;
unsigned int dwRBitMask;
unsigned int dwGBitMask;
unsigned int dwBBitMask;
unsigned int dwAlphaBitMask;
}
sPixelFormat;
/* DDCAPS2 */
struct
{
unsigned int dwCaps1;
unsigned int dwCaps2;
unsigned int dwDDSX;
unsigned int dwReserved;
}
sCaps;
unsigned int dwReserved2;
}
DDS_header ;
/* the following constants were copied directly off the MSDN website */
/* The dwFlags member of the original DDSURFACEDESC2 structure
can be set to one or more of the following values. */
#define DDSD_CAPS 0x00000001
#define DDSD_HEIGHT 0x00000002
#define DDSD_WIDTH 0x00000004
#define DDSD_PITCH 0x00000008
#define DDSD_PIXELFORMAT 0x00001000
#define DDSD_MIPMAPCOUNT 0x00020000
#define DDSD_LINEARSIZE 0x00080000
#define DDSD_DEPTH 0x00800000
/* DirectDraw Pixel Format */
#define DDPF_ALPHAPIXELS 0x00000001
#define DDPF_FOURCC 0x00000004
#define DDPF_RGB 0x00000040
/* The dwCaps1 member of the DDSCAPS2 structure can be
set to one or more of the following values. */
#define DDSCAPS_COMPLEX 0x00000008
#define DDSCAPS_TEXTURE 0x00001000
#define DDSCAPS_MIPMAP 0x00400000
/* The dwCaps2 member of the DDSCAPS2 structure can be
set to one or more of the following values. */
#define DDSCAPS2_CUBEMAP 0x00000200
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
#define DDSCAPS2_VOLUME 0x00200000
#endif /* HEADER_IMAGE_DXT */

View File

@ -0,0 +1,435 @@
/*
Jonathan Dummer
image helper functions
MIT license
*/
#include "image_helper.h"
#include <stdlib.h>
#include <math.h>
/* Upscaling the image uses simple bilinear interpolation */
int
up_scale_image
(
const unsigned char* const orig,
int width, int height, int channels,
unsigned char* resampled,
int resampled_width, int resampled_height
)
{
float dx, dy;
int x, y, c;
/* error(s) check */
if ( (width < 1) || (height < 1) ||
(resampled_width < 2) || (resampled_height < 2) ||
(channels < 1) ||
(NULL == orig) || (NULL == resampled) )
{
/* signify badness */
return 0;
}
/*
for each given pixel in the new map, find the exact location
from the original map which would contribute to this guy
*/
dx = (width - 1.0f) / (resampled_width - 1.0f);
dy = (height - 1.0f) / (resampled_height - 1.0f);
for ( y = 0; y < resampled_height; ++y )
{
/* find the base y index and fractional offset from that */
float sampley = y * dy;
int inty = (int)sampley;
/* if( inty < 0 ) { inty = 0; } else */
if( inty > height - 2 ) { inty = height - 2; }
sampley -= inty;
for ( x = 0; x < resampled_width; ++x )
{
float samplex = x * dx;
int intx = (int)samplex;
int base_index;
/* find the base x index and fractional offset from that */
/* if( intx < 0 ) { intx = 0; } else */
if( intx > width - 2 ) { intx = width - 2; }
samplex -= intx;
/* base index into the original image */
base_index = (inty * width + intx) * channels;
for ( c = 0; c < channels; ++c )
{
/* do the sampling */
float value = 0.5f;
value += orig[base_index]
*(1.0f-samplex)*(1.0f-sampley);
value += orig[base_index+channels]
*(samplex)*(1.0f-sampley);
value += orig[base_index+width*channels]
*(1.0f-samplex)*(sampley);
value += orig[base_index+width*channels+channels]
*(samplex)*(sampley);
/* move to the next channel */
++base_index;
/* save the new value */
resampled[y*resampled_width*channels+x*channels+c] =
(unsigned char)(value);
}
}
}
/* done */
return 1;
}
int
mipmap_image
(
const unsigned char* const orig,
int width, int height, int channels,
unsigned char* resampled,
int block_size_x, int block_size_y
)
{
int mip_width, mip_height;
int i, j, c;
/* error check */
if( (width < 1) || (height < 1) ||
(channels < 1) || (orig == NULL) ||
(resampled == NULL) ||
(block_size_x < 1) || (block_size_y < 1) )
{
/* nothing to do */
return 0;
}
mip_width = width / block_size_x;
mip_height = height / block_size_y;
if( mip_width < 1 )
{
mip_width = 1;
}
if( mip_height < 1 )
{
mip_height = 1;
}
for( j = 0; j < mip_height; ++j )
{
for( i = 0; i < mip_width; ++i )
{
for( c = 0; c < channels; ++c )
{
const int index = (j*block_size_y)*width*channels + (i*block_size_x)*channels + c;
int sum_value;
int u,v;
int u_block = block_size_x;
int v_block = block_size_y;
int block_area;
/* do a bit of checking so we don't over-run the boundaries
(necessary for non-square textures!) */
if( block_size_x * (i+1) > width )
{
u_block = width - i*block_size_y;
}
if( block_size_y * (j+1) > height )
{
v_block = height - j*block_size_y;
}
block_area = u_block*v_block;
/* for this pixel, see what the average
of all the values in the block are.
note: start the sum at the rounding value, not at 0 */
sum_value = block_area >> 1;
for( v = 0; v < v_block; ++v )
for( u = 0; u < u_block; ++u )
{
sum_value += orig[index + v*width*channels + u*channels];
}
resampled[j*mip_width*channels + i*channels + c] = sum_value / block_area;
}
}
}
return 1;
}
int
scale_image_RGB_to_NTSC_safe
(
unsigned char* orig,
int width, int height, int channels
)
{
const float scale_lo = 16.0f - 0.499f;
const float scale_hi = 235.0f + 0.499f;
int i, j;
int nc = channels;
unsigned char scale_LUT[256];
/* error check */
if( (width < 1) || (height < 1) ||
(channels < 1) || (orig == NULL) )
{
/* nothing to do */
return 0;
}
/* set up the scaling Look Up Table */
for( i = 0; i < 256; ++i )
{
scale_LUT[i] = (unsigned char)((scale_hi - scale_lo) * i / 255.0f + scale_lo);
}
/* for channels = 2 or 4, ignore the alpha component */
nc -= 1 - (channels & 1);
/* OK, go through the image and scale any non-alpha components */
for( i = 0; i < width*height*channels; i += channels )
{
for( j = 0; j < nc; ++j )
{
orig[i+j] = scale_LUT[orig[i+j]];
}
}
return 1;
}
unsigned char clamp_byte( int x ) { return ( (x) < 0 ? (0) : ( (x) > 255 ? 255 : (x) ) ); }
/*
This function takes the RGB components of the image
and converts them into YCoCg. 3 components will be
re-ordered to CoYCg (for optimum DXT1 compression),
while 4 components will be ordered CoCgAY (for DXT5
compression).
*/
int
convert_RGB_to_YCoCg
(
unsigned char* orig,
int width, int height, int channels
)
{
int i;
/* error check */
if( (width < 1) || (height < 1) ||
(channels < 3) || (channels > 4) ||
(orig == NULL) )
{
/* nothing to do */
return -1;
}
/* do the conversion */
if( channels == 3 )
{
for( i = 0; i < width*height*3; i += 3 )
{
int r = orig[i+0];
int g = (orig[i+1] + 1) >> 1;
int b = orig[i+2];
int tmp = (2 + r + b) >> 2;
/* Co */
orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
/* Y */
orig[i+1] = clamp_byte( g + tmp );
/* Cg */
orig[i+2] = clamp_byte( 128 + g - tmp );
}
} else
{
for( i = 0; i < width*height*4; i += 4 )
{
int r = orig[i+0];
int g = (orig[i+1] + 1) >> 1;
int b = orig[i+2];
unsigned char a = orig[i+3];
int tmp = (2 + r + b) >> 2;
/* Co */
orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
/* Cg */
orig[i+1] = clamp_byte( 128 + g - tmp );
/* Alpha */
orig[i+2] = a;
/* Y */
orig[i+3] = clamp_byte( g + tmp );
}
}
/* done */
return 0;
}
/*
This function takes the YCoCg components of the image
and converts them into RGB. See above.
*/
int
convert_YCoCg_to_RGB
(
unsigned char* orig,
int width, int height, int channels
)
{
int i;
/* error check */
if( (width < 1) || (height < 1) ||
(channels < 3) || (channels > 4) ||
(orig == NULL) )
{
/* nothing to do */
return -1;
}
/* do the conversion */
if( channels == 3 )
{
for( i = 0; i < width*height*3; i += 3 )
{
int co = orig[i+0] - 128;
int y = orig[i+1];
int cg = orig[i+2] - 128;
/* R */
orig[i+0] = clamp_byte( y + co - cg );
/* G */
orig[i+1] = clamp_byte( y + cg );
/* B */
orig[i+2] = clamp_byte( y - co - cg );
}
} else
{
for( i = 0; i < width*height*4; i += 4 )
{
int co = orig[i+0] - 128;
int cg = orig[i+1] - 128;
unsigned char a = orig[i+2];
int y = orig[i+3];
/* R */
orig[i+0] = clamp_byte( y + co - cg );
/* G */
orig[i+1] = clamp_byte( y + cg );
/* B */
orig[i+2] = clamp_byte( y - co - cg );
/* A */
orig[i+3] = a;
}
}
/* done */
return 0;
}
float
find_max_RGBE
(
unsigned char *image,
int width, int height
)
{
float max_val = 0.0f;
unsigned char *img = image;
int i, j;
for( i = width * height; i > 0; --i )
{
/* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
float scale = ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
for( j = 0; j < 3; ++j )
{
if( img[j] * scale > max_val )
{
max_val = img[j] * scale;
}
}
/* next pixel */
img += 4;
}
return max_val;
}
int
RGBE_to_RGBdivA
(
unsigned char *image,
int width, int height,
int rescale_to_max
)
{
/* local variables */
int i, iv;
unsigned char *img = image;
float scale = 1.0f;
/* error check */
if( (!image) || (width < 1) || (height < 1) )
{
return 0;
}
/* convert (note: no negative numbers, but 0.0 is possible) */
if( rescale_to_max )
{
scale = 255.0f / find_max_RGBE( image, width, height );
}
for( i = width * height; i > 0; --i )
{
/* decode this pixel, and find the max */
float r,g,b,e, m;
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
r = e * img[0];
g = e * img[1];
b = e * img[2];
m = (r > g) ? r : g;
m = (b > m) ? b : m;
/* and encode it into RGBdivA */
iv = (m != 0.0f) ? (int)(255.0f / m) : 1.0f;
iv = (iv < 1) ? 1 : iv;
img[3] = (iv > 255) ? 255 : iv;
iv = (int)(img[3] * r + 0.5f);
img[0] = (iv > 255) ? 255 : iv;
iv = (int)(img[3] * g + 0.5f);
img[1] = (iv > 255) ? 255 : iv;
iv = (int)(img[3] * b + 0.5f);
img[2] = (iv > 255) ? 255 : iv;
/* and on to the next pixel */
img += 4;
}
return 1;
}
int
RGBE_to_RGBdivA2
(
unsigned char *image,
int width, int height,
int rescale_to_max
)
{
/* local variables */
int i, iv;
unsigned char *img = image;
float scale = 1.0f;
/* error check */
if( (!image) || (width < 1) || (height < 1) )
{
return 0;
}
/* convert (note: no negative numbers, but 0.0 is possible) */
if( rescale_to_max )
{
scale = 255.0f * 255.0f / find_max_RGBE( image, width, height );
}
for( i = width * height; i > 0; --i )
{
/* decode this pixel, and find the max */
float r,g,b,e, m;
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
r = e * img[0];
g = e * img[1];
b = e * img[2];
m = (r > g) ? r : g;
m = (b > m) ? b : m;
/* and encode it into RGBdivA */
iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1.0f;
iv = (iv < 1) ? 1 : iv;
img[3] = (iv > 255) ? 255 : iv;
iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f);
img[0] = (iv > 255) ? 255 : iv;
iv = (int)(img[3] * img[3] * g / 255.0f + 0.5f);
img[1] = (iv > 255) ? 255 : iv;
iv = (int)(img[3] * img[3] * b / 255.0f + 0.5f);
img[2] = (iv > 255) ? 255 : iv;
/* and on to the next pixel */
img += 4;
}
return 1;
}

Some files were not shown because too many files have changed in this diff Show More