diff --git a/src/external/OpenCTM-1.0.3/COMPILING.txt b/src/external/OpenCTM-1.0.3/COMPILING.txt new file mode 100644 index 000000000..065e932fc --- /dev/null +++ b/src/external/OpenCTM-1.0.3/COMPILING.txt @@ -0,0 +1,100 @@ +1. PREREQUISITES +================ + +In order to compile the OpenCTM shared library, all you need is a supported +compiler and it should compile right out of the box. + +In order to compile the entire OpenCTM package, including documentation and the +tools, there are some extra dependencies: + +- To build all the tools, you need GLUT, and for Un*x/X11 you also need + GTK+ 2.0 (Ubuntu: sudo apt-get install libgtk2.0-dev). + +- To build the documentation you need Doxygen (www.doxygen.org), a full + LaTeX installation (see TeX Live - http://www.tug.org/texlive/), and Groff + (Windows: http://gnuwin32.sourceforge.net/packages/groff.htm, + Mac OS X: preinstalled, Ubuntu: sudo apt-get install groff). + + +2. COMPILING +============ + +There are a few makefiles for different systems and compilers. Just pick the +one that fits your system, and run "make" on the corresponding file. Here are +a few specific instructions: + + +2.1 Windows, MinGW32 +-------------------- + +mingw32-make -f Makefile.mingw + + +2.2 Windows, MS Visual Studio (Express) 2008 +-------------------------------------------- + +nmake /f Makefile.msvc + + +2.3 Mac OS X +------------ + +make -f Makefile.macosx + + +2.4 Linux +--------- + +make -f Makefile.linux + + +2.5 OpenSolaris +--------------- + +gmake -f Makefile.linux + + +3. BUILD TARGETS +================ + +By default, the OpenCTM shared library and the OpenCTM tools are compiled when +make is run. To select what is built, use one of the following build targets +(just append it to the end of the make command line): + + openctm (the shared library) + toolset (the tools) + documentation (the HTML and PDF documentation) + all (openctm + toolset + documentation) + clean (clean all the built files - start from scratch) + +For instance, to just build the OpenCTM shared library under Windows with +MS Visual Studio, type: + + nmake /f Makefile.msvc openctm + + +4. INSTALLATION +=============== + +For Linux and Mac OS X, it is possible to make a system wide installation by +using the "install" build target. The installation process will install the +following: + + - OpenCTM shared library + - OpenCTM C/C++ headers (inlcude files) + - ctmconv and ctmviewer tools + - Man pages + +Just make sure that the Makefile contains the correct (and desired) +installation paths. Also, you need to have root privileges to make a system +wide installation. + +For instance, to compile and install OpenCTM under Ubuntu, do: + +make -f Makefile.linux +sudo make -f Makefile.linux install + +...and to compile and install OpenCTM under Mac OS X, do: + +make -f Makefile.macosx +sudo make -f Makefile.macosx install diff --git a/src/external/OpenCTM-1.0.3/LICENSE.txt b/src/external/OpenCTM-1.0.3/LICENSE.txt new file mode 100644 index 000000000..0e66fa76e --- /dev/null +++ b/src/external/OpenCTM-1.0.3/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2009-2010 Marcus Geelnard + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. diff --git a/src/external/OpenCTM-1.0.3/Makefile.linux b/src/external/OpenCTM-1.0.3/Makefile.linux new file mode 100644 index 000000000..24ca13753 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/Makefile.linux @@ -0,0 +1,65 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.linux +# Description: Top level makefile for Linux systems (should work on most +# Un*x-like systems with gcc, e.g. OpenSolaris). +############################################################################### +# Copyright (c) 2009 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +.phony: default all openctm toolset documentation install clean + +default: openctm toolset +all: openctm toolset documentation + +clean: + cd lib && $(MAKE) -f Makefile.linux clean && cd .. + cd tools && $(MAKE) -f Makefile.linux clean && cd .. + cd doc && $(MAKE) -f Makefile.linux clean && cd .. + +openctm: + cd lib && $(MAKE) -f Makefile.linux -j2 && cd .. + +toolset: + cd tools && $(MAKE) -f Makefile.linux -j2 && cd .. + +documentation: + cd doc && $(MAKE) -f Makefile.linux -j2 && cd .. + + +# Installation settings +LIBDIR = /usr/lib/ +INCDIR = /usr/local/include/ +BINDIR = /usr/local/bin/ +MAN1DIR = /usr/local/share/man/man1/ +CP = cp +MKDIR = mkdir -p + +install: + $(CP) lib/libopenctm.so $(LIBDIR) + $(CP) lib/openctm.h $(INCDIR) + $(CP) lib/openctmpp.h $(INCDIR) + $(CP) tools/ctmconv $(BINDIR) + $(CP) tools/ctmviewer $(BINDIR) + $(MKDIR) $(MAN1DIR) + $(CP) doc/ctmconv.1 $(MAN1DIR) + $(CP) doc/ctmviewer.1 $(MAN1DIR) diff --git a/src/external/OpenCTM-1.0.3/Makefile.macosx b/src/external/OpenCTM-1.0.3/Makefile.macosx new file mode 100644 index 000000000..16c804b99 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/Makefile.macosx @@ -0,0 +1,64 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.macosx +# Description: Top level makefile for Mac OS X. +############################################################################### +# Copyright (c) 2009 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +.phony: default all openctm toolset documentation clean + +default: openctm toolset +all: openctm toolset documentation + +clean: + cd lib && $(MAKE) -f Makefile.macosx clean && cd .. + cd tools && $(MAKE) -f Makefile.macosx clean && cd .. + cd doc && $(MAKE) -f Makefile.macosx clean && cd .. + +openctm: + cd lib && $(MAKE) -f Makefile.macosx -j2 && cd .. + +toolset: + cd tools && $(MAKE) -f Makefile.macosx -j2 && cd .. + +documentation: + cd doc && $(MAKE) -f Makefile.macosx -j2 && cd .. + + +# Installation settings +LIBDIR = /usr/local/lib/ +INCDIR = /usr/local/include/ +BINDIR = /usr/local/bin/ +MAN1DIR = /usr/local/share/man/man1/ +CP = cp +MKDIR = mkdir -p + +install: + $(CP) lib/libopenctm.dylib $(LIBDIR) + $(CP) lib/openctm.h $(INCDIR) + $(CP) lib/openctmpp.h $(INCDIR) + $(CP) tools/ctmconv $(BINDIR) + $(CP) tools/ctmviewer $(BINDIR) + $(MKDIR) $(MAN1DIR) + $(CP) doc/ctmconv.1 $(MAN1DIR) + $(CP) doc/ctmviewer.1 $(MAN1DIR) diff --git a/src/external/OpenCTM-1.0.3/Makefile.mingw b/src/external/OpenCTM-1.0.3/Makefile.mingw new file mode 100644 index 000000000..bf67cdced --- /dev/null +++ b/src/external/OpenCTM-1.0.3/Makefile.mingw @@ -0,0 +1,45 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.mingw +# Description: Top level makefile for Windows / MinGW32. +############################################################################### +# Copyright (c) 2009 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +.phony: default all openctm toolset documentation clean + +default: openctm toolset +all: openctm toolset documentation + +clean: + cd lib && $(MAKE) -f Makefile.mingw clean && cd .. + cd tools && $(MAKE) -f Makefile.mingw clean && cd .. + cd doc && $(MAKE) -f Makefile.win clean && cd .. + +openctm: + cd lib && $(MAKE) -f Makefile.mingw -j2 && cd .. + +toolset: + cd tools && $(MAKE) -f Makefile.mingw -j2 && cd .. + +documentation: + cd doc && $(MAKE) -f Makefile.win -j2 && cd .. diff --git a/src/external/OpenCTM-1.0.3/Makefile.msvc b/src/external/OpenCTM-1.0.3/Makefile.msvc new file mode 100644 index 000000000..ad3cbfae7 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/Makefile.msvc @@ -0,0 +1,45 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.msvc +# Description: Top level makefile for Windows / MS Visual Studio 2008. +############################################################################### +# Copyright (c) 2009 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +.PHONY: default all openctm toolset documentation clean + +default: openctm toolset +all: openctm toolset documentation + +clean: + cd lib && $(MAKE) /nologo /f Makefile.msvc clean && cd .. + cd tools && $(MAKE) /nologo /f Makefile.msvc clean && cd .. + cd doc && $(MAKE) /nologo /f Makefile.win clean && cd .. + +openctm: + cd lib && $(MAKE) /nologo /f Makefile.msvc && cd .. + +toolset: + cd tools && $(MAKE) /nologo /f Makefile.msvc && cd .. + +documentation: + cd doc && $(MAKE) /nologo /f Makefile.win && cd .. diff --git a/src/external/OpenCTM-1.0.3/README.txt b/src/external/OpenCTM-1.0.3/README.txt new file mode 100644 index 000000000..f7d1429c4 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/README.txt @@ -0,0 +1,152 @@ +1. INTRODUCTION +=============== + +Welcome to OpenCTM! + +OpenCTM is a file format, a software library and a tool set for compression of +3D triangle meshes. The geometry is compressed to a fraction of comparable file +formats (3DS, STL, COLLADA, VRML...), and the format is easily accessible +through a simple, portable API. + +The library is written in portable C (C99), and should compile nicely on any +32/64-bit system regardless of endianity (big endian or little endian). + + +2. LICENSE +========== + +The OpenCTM API and the OpenCTM tools are released under the zlib/libpng +license (see LICENSE.txt). + +3. CREDITS +========== + +Many people have helped out in the development process of OpenCTM, with +valuable feedback, programming efforts, test models and conceptual ideas. +Also, OpenCTM relies heavily on many other open source projects. + +Here is an incomplete list of persons that deserve credit: + +- Igor Pavlov (LZMA library) +- Jonas Innala (COLLADA importer, Maya exporter plugin) +- Ilian Dinev (help with the OpenCTM file format design and the LWO loader) +- Lee Thomason (TinyXML) +- Diego Nehab (RPly - for loading PLY files) +- Lev Povalahev, Marcelo E. Magallon, Milan Ikits (GLEW) +- Thomas G. Lane, Guido Vollbeding (libjpeg) +- Jean-loup Gailly, Mark Adler (zlib) +- Daniel Karling (pnglite) + +During the development of OpenCTM, the following software has been used +extensively: + +- Ubuntu (www.ubuntu.com) +- Blender (www.blender.org) +- GCC (gcc.gnu.org) +- SciTE (www.scintilla.org/SciTE.html) +- Notepad++ (notepad-plus.sourceforge.net) +- Smultron (smultron.sourceforge.net) + +Legal notices: + +- This software is based in part on the work of the Independent JPEG Group. + + +4. CHANGES +========== + +v1.0.3 - 2010.01.15 +------------------- +- Added support for PNG format textures (ctmviewer). + +- Added support for LightWave LWO files (ctmconv and ctmviewer). + +- Added support for Geomview OFF files, e.g. as used by the Princeton Shape + Benchmark (ctmconv and ctmviewer). + +- Improved the OBJ file loader (ctmviewer and ctmconv). + +- Experimental support for VRML 2.0 files - export only (ctmconv and ctmviewer). + +- Made it possible to run ctmviewer without command line arguments. + +- Improved the normal calculation algorithm (ctmviewer and ctmconv). + +- Normals are no longer exported if no normals were present in the input file + (ctmviewer). + + +v1.0.2 - 2009.12.13 +------------------- +- Added an OpenCTM exporter plugin for Maya [Jonas Innala]. + +- Added the possiblity to save and load files from ctmviewer, effectively + turning it into a quick and simple converter tool (without all the options + in the ctmconv program, though). + +- Added a function to load texture files from ctmviewer. + +- Improved the camera control in ctmviewer (panning with the right mouse + button, zooming with the middle mouse button and the mouse wheel, feature + focusing by double clicking, Y/Z up axis selection and "fit to screen" + function). + +- Added a GUI dialog for showing errors in ctmviewer (this is especially useful + under Windows, where console output is disabeled). + +- Added an option for calculating the normals in ctmconv (if the input file + does not have normals). + +- Added options for turning off normals, texture coordinates and/or vertex + colors for the output file in ctmconv. + +- Added manuals for ctmviewer and ctmconv (man pages). + +- Added a "make install" build target for Mac OS X and Linux for simple system + wide installation (see COMPILING.txt). + +- NOTE: The Linux/X11 version of ctmviewer now reqires GTK+ 2.0. + + +v1.0.1 - 2009.11.15 +------------------- +- Notable reduction of the memory footprint by tuning of the LZMA compression + parameters. + +- Added a Wavefront OBJ file importer/exporter. + +- Some improvements to ctmviewer and ctmconv. + +- Some directory structure and build system cleanups. + + +v1.0 - 2009.11.09 +----------------- +- Added a COLLADA converter module to the ctmconv program [Jonas Innala]. + +- Added Python bindings and a demo Python program. + +- Improved the internal mesh integrity checking, to minimize the risk of invalid + data processing. + +- Improved the file format specification document. + + +v0.8 (beta) - 2009.09.14 +------------------------ +- Introduced a new API function for controlling the compression level + (ctmCompressionLevel), and set the default compression level to 5 (rather + than 9, which would eat a lot of memory, usally without much difference). + +- Changed the name "texture map" in the API to "UV map" (and all + corresponding constant and function names). This is more in line with + the nomenclature of most 3D authoring software, and avoids the confusion + with the term texture mapping in 3D hardware (which is not limited to + 2D UV mapping coordinates). + +- A few updates to the documentation. + + +v0.7 (beta) - 2009.08.29 +------------------------ +- This was the first public release of OpenCTM. diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/annotated.html b/src/external/OpenCTM-1.0.3/doc/APIReference/annotated.html new file mode 100644 index 000000000..3658d4522 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/annotated.html @@ -0,0 +1,38 @@ + + + + +OpenCTM: Class List + + + + + + +
+

Class List

Here are the classes, structs, unions and interfaces with brief descriptions: + + + +
ctm_errorOpenCTM exception
CTMexporterOpenCTM exporter class
CTMimporterOpenCTM importer class
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter-members.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter-members.html new file mode 100644 index 000000000..dacb9434c --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter-members.html @@ -0,0 +1,51 @@ + + + + +OpenCTM: Member List + + + + + + +
+

CTMexporter Member List

This is the complete list of members for CTMexporter, including all inherited members. + + + + + + + + + + + + + + + + + +
AddAttribMap(const CTMfloat *aAttribValues, const char *aName)CTMexporter [inline]
AddUVMap(const CTMfloat *aUVCoords, const char *aName, const char *aFileName)CTMexporter [inline]
AttribPrecision(CTMenum aAttribMap, CTMfloat aPrecision)CTMexporter [inline]
CompressionLevel(CTMuint aLevel)CTMexporter [inline]
CompressionMethod(CTMenum aMethod)CTMexporter [inline]
CTMexporter()CTMexporter [inline]
CTMexporter(const CTMexporter &v)CTMexporter
DefineMesh(const CTMfloat *aVertices, CTMuint aVertexCount, const CTMuint *aIndices, CTMuint aTriangleCount, const CTMfloat *aNormals)CTMexporter [inline]
FileComment(const char *aFileComment)CTMexporter [inline]
NormalPrecision(CTMfloat aPrecision)CTMexporter [inline]
operator=(const CTMexporter &v)CTMexporter
Save(const char *aFileName)CTMexporter [inline]
SaveCustom(CTMwritefn aWriteFn, void *aUserData)CTMexporter [inline]
UVCoordPrecision(CTMenum aUVMap, CTMfloat aPrecision)CTMexporter [inline]
VertexPrecision(CTMfloat aPrecision)CTMexporter [inline]
VertexPrecisionRel(CTMfloat aRelPrecision)CTMexporter [inline]
~CTMexporter()CTMexporter [inline]
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter.html new file mode 100644 index 000000000..f97cfa5a2 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMexporter.html @@ -0,0 +1,508 @@ + + + + +OpenCTM: CTMexporter Class Reference + + + + + + +
+

CTMexporter Class Reference

+

OpenCTM exporter class. +More...

+ +

#include <openctmpp.h>

+ +

List of all members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

 CTMexporter ()
 Constructor.
 ~CTMexporter ()
 Destructor.
void CompressionMethod (CTMenum aMethod)
 Wrapper for ctmCompressionMethod().
void CompressionLevel (CTMuint aLevel)
 Wrapper for ctmCompressionLevel().
void VertexPrecision (CTMfloat aPrecision)
 Wrapper for ctmVertexPrecision().
void VertexPrecisionRel (CTMfloat aRelPrecision)
 Wrapper for ctmVertexPrecisionRel().
void NormalPrecision (CTMfloat aPrecision)
 Wrapper for ctmNormalPrecision().
void UVCoordPrecision (CTMenum aUVMap, CTMfloat aPrecision)
 Wrapper for ctmUVCoordPrecision().
void AttribPrecision (CTMenum aAttribMap, CTMfloat aPrecision)
 Wrapper for ctmAttribPrecision().
void FileComment (const char *aFileComment)
 Wrapper for ctmFileComment().
void DefineMesh (const CTMfloat *aVertices, CTMuint aVertexCount, const CTMuint *aIndices, CTMuint aTriangleCount, const CTMfloat *aNormals)
 Wrapper for ctmDefineMesh().
CTMenum AddUVMap (const CTMfloat *aUVCoords, const char *aName, const char *aFileName)
 Wrapper for ctmAddUVMap().
CTMenum AddAttribMap (const CTMfloat *aAttribValues, const char *aName)
 Wrapper for ctmAddAttribMap().
void Save (const char *aFileName)
 Wrapper for ctmSave().
void SaveCustom (CTMwritefn aWriteFn, void *aUserData)
 Wrapper for ctmSaveCustom().
 CTMexporter (const CTMexporter &v)
CTMexporteroperator= (const CTMexporter &v)
+

Detailed Description

+

OpenCTM exporter class.

+

This is a C++ wrapper class for an OpenCTM export context. Usage example:

+
 void MySaveFile(CTMuint aVertCount, CTMuint aTriCount, CTMfloat * aVertices,
+   CTMuint * aIndices, const char * aFileName)
+ {
+   // Create a new OpenCTM exporter object
+   CTMexporter ctm;
+
+   // Define our mesh representation to OpenCTM (store references to it in
+   // the context)
+   ctm.DefineMesh(aVertices, aVertCount, aIndices, aTriCount, NULL);
+
+   // Save the OpenCTM file
+   ctm.Save(aFileName);
+ }
+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
CTMexporter::CTMexporter ( )  [inline]
+
+
+ +

Constructor.

+ +
+
+ +
+
+ + + + + + + + +
CTMexporter::~CTMexporter ( )  [inline]
+
+
+ +

Destructor.

+ +
+
+ +
+
+ + + + + + + + + +
CTMexporter::CTMexporter (const CTMexporter v ) 
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMenum CTMexporter::AddAttribMap (const CTMfloat aAttribValues,
const char *  aName 
) [inline]
+
+
+ +

Wrapper for ctmAddAttribMap().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMenum CTMexporter::AddUVMap (const CTMfloat aUVCoords,
const char *  aName,
const char *  aFileName 
) [inline]
+
+
+ +

Wrapper for ctmAddUVMap().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void CTMexporter::AttribPrecision (CTMenum  aAttribMap,
CTMfloat  aPrecision 
) [inline]
+
+
+ +

Wrapper for ctmAttribPrecision().

+ +
+
+ +
+
+ + + + + + + + + +
void CTMexporter::CompressionLevel (CTMuint  aLevel )  [inline]
+
+
+ +

Wrapper for ctmCompressionLevel().

+ +
+
+ +
+
+ + + + + + + + + +
void CTMexporter::CompressionMethod (CTMenum  aMethod )  [inline]
+
+
+ +

Wrapper for ctmCompressionMethod().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
void CTMexporter::DefineMesh (const CTMfloat aVertices,
CTMuint  aVertexCount,
const CTMuint aIndices,
CTMuint  aTriangleCount,
const CTMfloat aNormals 
) [inline]
+
+
+ +

Wrapper for ctmDefineMesh().

+ +
+
+ +
+
+ + + + + + + + + +
void CTMexporter::FileComment (const char *  aFileComment )  [inline]
+
+
+ +

Wrapper for ctmFileComment().

+ +
+
+ +
+
+ + + + + + + + + +
void CTMexporter::NormalPrecision (CTMfloat  aPrecision )  [inline]
+
+
+ +

Wrapper for ctmNormalPrecision().

+ +
+
+ +
+
+ + + + + + + + + +
CTMexporter& CTMexporter::operator= (const CTMexporter v ) 
+
+
+ +
+
+ +
+
+ + + + + + + + + +
void CTMexporter::Save (const char *  aFileName )  [inline]
+
+
+ +

Wrapper for ctmSave().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void CTMexporter::SaveCustom (CTMwritefn  aWriteFn,
void *  aUserData 
) [inline]
+
+
+ +

Wrapper for ctmSaveCustom().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void CTMexporter::UVCoordPrecision (CTMenum  aUVMap,
CTMfloat  aPrecision 
) [inline]
+
+
+ +

Wrapper for ctmUVCoordPrecision().

+ +
+
+ +
+
+ + + + + + + + + +
void CTMexporter::VertexPrecision (CTMfloat  aPrecision )  [inline]
+
+
+ +

Wrapper for ctmVertexPrecision().

+ +
+
+ +
+
+ + + + + + + + + +
void CTMexporter::VertexPrecisionRel (CTMfloat  aRelPrecision )  [inline]
+
+
+ +

Wrapper for ctmVertexPrecisionRel().

+ +
+
+
The documentation for this class was generated from the following file: +
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter-members.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter-members.html new file mode 100644 index 000000000..2b2b0769e --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter-members.html @@ -0,0 +1,51 @@ + + + + +OpenCTM: Member List + + + + + + +
+

CTMimporter Member List

This is the complete list of members for CTMimporter, including all inherited members. + + + + + + + + + + + + + + + + + +
CTMimporter()CTMimporter [inline]
CTMimporter(const CTMimporter &v)CTMimporter
GetAttribMapFloat(CTMenum aAttribMap, CTMenum aProperty)CTMimporter [inline]
GetAttribMapString(CTMenum aAttribMap, CTMenum aProperty)CTMimporter [inline]
GetFloat(CTMenum aProperty)CTMimporter [inline]
GetFloatArray(CTMenum aProperty)CTMimporter [inline]
GetInteger(CTMenum aProperty)CTMimporter [inline]
GetIntegerArray(CTMenum aProperty)CTMimporter [inline]
GetNamedAttribMap(const char *aName)CTMimporter [inline]
GetNamedUVMap(const char *aName)CTMimporter [inline]
GetString(CTMenum aProperty)CTMimporter [inline]
GetUVMapFloat(CTMenum aUVMap, CTMenum aProperty)CTMimporter [inline]
GetUVMapString(CTMenum aUVMap, CTMenum aProperty)CTMimporter [inline]
Load(const char *aFileName)CTMimporter [inline]
LoadCustom(CTMreadfn aReadFn, void *aUserData)CTMimporter [inline]
operator=(const CTMimporter &v)CTMimporter
~CTMimporter()CTMimporter [inline]
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter.html new file mode 100644 index 000000000..19bfa2aba --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/classCTMimporter.html @@ -0,0 +1,476 @@ + + + + +OpenCTM: CTMimporter Class Reference + + + + + + +
+

CTMimporter Class Reference

+

OpenCTM importer class. +More...

+ +

#include <openctmpp.h>

+ +

List of all members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Public Member Functions

 CTMimporter ()
 Constructor.
 ~CTMimporter ()
 Destructor.
CTMuint GetInteger (CTMenum aProperty)
 Wrapper for ctmGetInteger().
CTMfloat GetFloat (CTMenum aProperty)
 Wrapper for ctmGetFloat().
const CTMuintGetIntegerArray (CTMenum aProperty)
 Wrapper for ctmGetIntegerArray().
const CTMfloatGetFloatArray (CTMenum aProperty)
 Wrapper for ctmGetFloatArray().
CTMenum GetNamedUVMap (const char *aName)
 Wrapper for ctmGetNamedUVMap().
const char * GetUVMapString (CTMenum aUVMap, CTMenum aProperty)
 Wrapper for ctmGetUVMapString().
CTMfloat GetUVMapFloat (CTMenum aUVMap, CTMenum aProperty)
 Wrapper for ctmGetUVMapFloat().
CTMenum GetNamedAttribMap (const char *aName)
 Wrapper for ctmGetNamedAttribMap().
const char * GetAttribMapString (CTMenum aAttribMap, CTMenum aProperty)
 Wrapper for ctmGetAttribMapString().
CTMfloat GetAttribMapFloat (CTMenum aAttribMap, CTMenum aProperty)
 Wrapper for ctmGetAttribMapFloat().
const char * GetString (CTMenum aProperty)
 Wrapper for ctmGetString().
void Load (const char *aFileName)
 Wrapper for ctmLoad().
void LoadCustom (CTMreadfn aReadFn, void *aUserData)
 Wrapper for ctmLoadCustom().
 CTMimporter (const CTMimporter &v)
CTMimporteroperator= (const CTMimporter &v)
+

Detailed Description

+

OpenCTM importer class.

+

This is a C++ wrapper class for an OpenCTM import context. Usage example:

+
   // Create a new OpenCTM importer object
+   CTMimporter ctm;
+
+   // Load the OpenCTM file
+   ctm.Load("mymesh.ctm");
+
+   // Access the mesh data
+   vertCount = ctm.GetInteger(CTM_VERTEX_COUNT);
+   vertices = ctm.GetFloatArray(CTM_VERTICES);
+   triCount = ctm.GetInteger(CTM_TRIANGLE_COUNT);
+   indices = ctm.GetIntegerArray(CTM_INDICES);
+
+   // Deal with the mesh (e.g. transcode it to our internal representation)
+   // ...
+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + +
CTMimporter::CTMimporter ( )  [inline]
+
+
+ +

Constructor.

+ +
+
+ +
+
+ + + + + + + + +
CTMimporter::~CTMimporter ( )  [inline]
+
+
+ +

Destructor.

+ +
+
+ +
+
+ + + + + + + + + +
CTMimporter::CTMimporter (const CTMimporter v ) 
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMfloat CTMimporter::GetAttribMapFloat (CTMenum  aAttribMap,
CTMenum  aProperty 
) [inline]
+
+
+ +

Wrapper for ctmGetAttribMapFloat().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
const char* CTMimporter::GetAttribMapString (CTMenum  aAttribMap,
CTMenum  aProperty 
) [inline]
+
+
+ +

Wrapper for ctmGetAttribMapString().

+ +
+
+ +
+
+ + + + + + + + + +
CTMfloat CTMimporter::GetFloat (CTMenum  aProperty )  [inline]
+
+
+ +

Wrapper for ctmGetFloat().

+ +
+
+ +
+
+ + + + + + + + + +
const CTMfloat* CTMimporter::GetFloatArray (CTMenum  aProperty )  [inline]
+
+
+ +

Wrapper for ctmGetFloatArray().

+ +
+
+ +
+
+ + + + + + + + + +
CTMuint CTMimporter::GetInteger (CTMenum  aProperty )  [inline]
+
+
+ +

Wrapper for ctmGetInteger().

+ +
+
+ +
+
+ + + + + + + + + +
const CTMuint* CTMimporter::GetIntegerArray (CTMenum  aProperty )  [inline]
+
+
+ +

Wrapper for ctmGetIntegerArray().

+ +
+
+ +
+
+ + + + + + + + + +
CTMenum CTMimporter::GetNamedAttribMap (const char *  aName )  [inline]
+
+
+ +

Wrapper for ctmGetNamedAttribMap().

+ +
+
+ +
+
+ + + + + + + + + +
CTMenum CTMimporter::GetNamedUVMap (const char *  aName )  [inline]
+
+
+ +

Wrapper for ctmGetNamedUVMap().

+ +
+
+ +
+
+ + + + + + + + + +
const char* CTMimporter::GetString (CTMenum  aProperty )  [inline]
+
+
+ +

Wrapper for ctmGetString().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMfloat CTMimporter::GetUVMapFloat (CTMenum  aUVMap,
CTMenum  aProperty 
) [inline]
+
+
+ +

Wrapper for ctmGetUVMapFloat().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
const char* CTMimporter::GetUVMapString (CTMenum  aUVMap,
CTMenum  aProperty 
) [inline]
+
+
+ +

Wrapper for ctmGetUVMapString().

+ +
+
+ +
+
+ + + + + + + + + +
void CTMimporter::Load (const char *  aFileName )  [inline]
+
+
+ +

Wrapper for ctmLoad().

+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
void CTMimporter::LoadCustom (CTMreadfn  aReadFn,
void *  aUserData 
) [inline]
+
+
+ +

Wrapper for ctmLoadCustom().

+ +
+
+ +
+
+ + + + + + + + + +
CTMimporter& CTMimporter::operator= (const CTMimporter v ) 
+
+
+ +
+
+
The documentation for this class was generated from the following file: +
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error-members.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error-members.html new file mode 100644 index 000000000..808972cb9 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error-members.html @@ -0,0 +1,37 @@ + + + + +OpenCTM: Member List + + + + + + +
+

ctm_error Member List

This is the complete list of members for ctm_error, including all inherited members. + + + +
ctm_error(CTMenum aError)ctm_error [inline, explicit]
error_code() const ctm_error [inline]
what() const ctm_error [inline, virtual]
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error.html new file mode 100644 index 000000000..c75b0790a --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/classctm__error.html @@ -0,0 +1,106 @@ + + + + +OpenCTM: ctm_error Class Reference + + + + + + +
+

ctm_error Class Reference

+

OpenCTM exception. +More...

+ +

#include <openctmpp.h>

+ +

List of all members.

+ + + + + +

Public Member Functions

 ctm_error (CTMenum aError)
virtual const char * what () const throw ()
CTMenum error_code () const throw ()
+

Detailed Description

+

OpenCTM exception.

+

When an error occurs, a ctm_error exception is thrown. Its what() function returns the name of the OpenCTM error code (for instance "CTM_INVALID_OPERATION").

+

Constructor & Destructor Documentation

+ +
+
+ + + + + + + + + +
ctm_error::ctm_error (CTMenum  aError )  [inline, explicit]
+
+
+ +
+
+

Member Function Documentation

+ +
+
+ + + + + + + + +
CTMenum ctm_error::error_code ( )  const throw () [inline]
+
+
+ +
+
+ +
+
+ + + + + + + + +
virtual const char* ctm_error::what ( )  const throw () [inline, virtual]
+
+
+ +
+
+
The documentation for this class was generated from the following file: +
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/classes.html b/src/external/OpenCTM-1.0.3/doc/APIReference/classes.html new file mode 100644 index 000000000..866996cc7 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/classes.html @@ -0,0 +1,37 @@ + + + + +OpenCTM: Alphabetical List + + + + + + +
+

Class Index

C
+ +
  C  
+
ctm_error   CTMexporter   CTMimporter   
C
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.css b/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.css new file mode 100644 index 000000000..9ca3cafbc --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.css @@ -0,0 +1,498 @@ +/* The standard CSS for doxygen */ + +body, table, div, p, dl { + font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif; + font-size: 12px; +} + +/* @group Heading Levels */ + +h1 { + text-align: center; + font-size: 150%; +} + +h2 { + font-size: 120%; +} + +h3 { + font-size: 100%; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #153788; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #1b77c5; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code { +} + +a.codeRef { +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +.fragment { + font-family: monospace, fixed; + font-size: 105%; +} + +pre.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + padding: 4px 6px; + margin: 4px 8px 4px 2px; +} + +div.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} + +td.indexkey { + background-color: #e8eef2; + font-weight: bold; + border: 1px solid #CCCCCC; + margin: 2px 0px 2px 0; + padding: 2px 10px; +} + +td.indexvalue { + background-color: #e8eef2; + border: 1px solid #CCCCCC; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #f0f0f0; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +/* @end */ + +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} + +th.dirtab { + background: #e8eef2; + font-weight: bold; +} + +hr { + height: 0; + border: none; + border-top: 1px solid #666; +} + +/* @group Member Descriptions */ + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #FAFAFA; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memItemLeft, .memItemRight, .memTemplParams { + border-top: 1px solid #ccc; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memTemplParams { + color: #606060; + white-space: nowrap; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #606060; + font-weight: normal; + margin-left: 3px; +} + +.memnav { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.memitem { + padding: 0; + margin-bottom: 10px; +} + +.memname { + white-space: nowrap; + font-weight: bold; +} + +.memproto, .memdoc { + border: 1px solid #84b0c7; +} + +.memproto { + padding: 0; + background-color: #d5e1e8; + font-weight: bold; + -webkit-border-top-left-radius: 8px; + -webkit-border-top-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -moz-border-radius-topleft: 8px; + -moz-border-radius-topright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + +} + +.memdoc { + padding: 2px 5px; + background-color: #eef3f5; + border-top-width: 0; + -webkit-border-bottom-left-radius: 8px; + -webkit-border-bottom-right-radius: 8px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -moz-border-radius-bottomleft: 8px; + -moz-border-radius-bottomright: 8px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} + +/* @end */ + +/* @group Directory (tree) */ + +/* for the tree view */ + +.ftvtree { + font-family: sans-serif; + margin: 0.5em; +} + +/* these are for tree view when used as main index */ + +.directory { + font-size: 9pt; + font-weight: bold; +} + +.directory h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +/* +The following two styles can be used to replace the root node title +with an image of your choice. Simply uncomment the next two styles, +specify the name of your image and be sure to set 'height' to the +proper pixel height of your image. +*/ + +/* +.directory h3.swap { + height: 61px; + background-repeat: no-repeat; + background-image: url("yourimage.gif"); +} +.directory h3.swap span { + display: none; +} +*/ + +.directory > h3 { + margin-top: 0; +} + +.directory p { + margin: 0px; + white-space: nowrap; +} + +.directory div { + display: none; + margin: 0px; +} + +.directory img { + vertical-align: -30%; +} + +/* these are for tree view when not used as main index */ + +.directory-alt { + font-size: 100%; + font-weight: bold; +} + +.directory-alt h3 { + margin: 0px; + margin-top: 1em; + font-size: 11pt; +} + +.directory-alt > h3 { + margin-top: 0; +} + +.directory-alt p { + margin: 0px; + white-space: nowrap; +} + +.directory-alt div { + display: none; + margin: 0px; +} + +.directory-alt img { + vertical-align: -30%; +} + +/* @end */ + +address { + font-style: normal; + color: #333; +} diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.png b/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.png new file mode 100644 index 000000000..f0a274bba Binary files /dev/null and b/src/external/OpenCTM-1.0.3/doc/APIReference/doxygen.png differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/files.html b/src/external/OpenCTM-1.0.3/doc/APIReference/files.html new file mode 100644 index 000000000..3d4691c98 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/files.html @@ -0,0 +1,37 @@ + + + + +OpenCTM: File Index + + + + + + +
+

File List

Here is a list of all files with brief descriptions: + + +
openctm.h [code]
openctmpp.h [code]
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/functions.html b/src/external/OpenCTM-1.0.3/doc/APIReference/functions.html new file mode 100644 index 000000000..2dd69a021 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/functions.html @@ -0,0 +1,216 @@ + + + + +OpenCTM: Class Members + + + + + + +
+Here is a list of all class members with links to the classes they belong to: + +

- a -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- l -

+ + +

- n -

+ + +

- o -

+ + +

- s -

+ + +

- u -

+ + +

- v -

+ + +

- w -

+ + +

- ~ -

+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/functions_func.html b/src/external/OpenCTM-1.0.3/doc/APIReference/functions_func.html new file mode 100644 index 000000000..df20fa4f7 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/functions_func.html @@ -0,0 +1,216 @@ + + + + +OpenCTM: Class Members - Functions + + + + + + +
+  + +

- a -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- l -

+ + +

- n -

+ + +

- o -

+ + +

- s -

+ + +

- u -

+ + +

- v -

+ + +

- w -

+ + +

- ~ -

+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals.html new file mode 100644 index 000000000..e0bc7b0b6 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/globals.html @@ -0,0 +1,313 @@ + + + + +OpenCTM: Class Members + + + + + + +
+Here is a list of all file members with links to the files they belong to: + +

- c -

+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_defs.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_defs.html new file mode 100644 index 000000000..3c5815d65 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_defs.html @@ -0,0 +1,54 @@ + + + + +OpenCTM: Class Members + + + + + + +
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_enum.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_enum.html new file mode 100644 index 000000000..bf3d826bd --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_enum.html @@ -0,0 +1,48 @@ + + + + +OpenCTM: Class Members + + + + + + +
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_eval.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_eval.html new file mode 100644 index 000000000..9f23a4d95 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_eval.html @@ -0,0 +1,193 @@ + + + + +OpenCTM: Class Members + + + + + + +
+  + +

- c -

+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_func.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_func.html new file mode 100644 index 000000000..da41c09e8 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_func.html @@ -0,0 +1,135 @@ + + + + +OpenCTM: Class Members + + + + + + +
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/globals_type.html b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_type.html new file mode 100644 index 000000000..1986f7f44 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/globals_type.html @@ -0,0 +1,63 @@ + + + + +OpenCTM: Class Members + + + + + + +
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/index.html b/src/external/OpenCTM-1.0.3/doc/APIReference/index.html new file mode 100644 index 000000000..72eba302c --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/index.html @@ -0,0 +1,93 @@ + + + + +OpenCTM: OpenCTM API Reference + + + + + + +
+

OpenCTM API Reference

1.0.3

+Introduction

+

OpenCTM is an open file format for storing compressed triangle meshes. In order to easily read and write OpenCTM files (usually suffixed .ctm) an API (Application Program Interface) is provided that can easily be used from most modern programming languages.

+

The OpenCTM functionality itself is written in highly portable standard C (C99).

+

+Usage

+

For information about how to use the OpenCTM API, see openctm.h.

+

For information about the C++ wrapper classes, see CTMimporter and CTMexporter.

+

+Example usage

+

+Loading a CTM file

+

Here is a simple example of loading a CTM file:

+
   CTMcontext context;
+   CTMuint    vertCount, triCount, * indices;
+   CTMfloat   * vertices;
+
+   // Create a new context
+   context = ctmNewContext(CTM_IMPORT);
+
+   // Load the OpenCTM file
+   ctmLoad(context, "mymesh.ctm");
+   if(ctmGetError(context) == CTM_NONE)
+   {
+     // Access the mesh data
+     vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT);
+     vertices = ctmGetFloatArray(context, CTM_VERTICES);
+     triCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT);
+     indices = ctmGetIntegerArray(context, CTM_INDICES);
+
+     // Deal with the mesh (e.g. transcode it to our internal representation)
+     // ...
+   }
+
+   // Free the context
+   ctmFreeContext(context);
+

+Creating a CTM file

+

Here is a simple example of creating a CTM file:

+
   CTMcontext context;
+   CTMuint    vertCount, triCount, * indices;
+   CTMfloat   * vertices;
+
+   // Create our mesh in memory
+   vertCount = 100;
+   triCount = 120;
+   vertices = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * vertCount);
+   indices = (CTMuint *) malloc(3 * sizeof(CTMuint) * triCount);
+   // ...
+
+   // Create a new context
+   context = ctmNewContext(CTM_EXPORT);
+
+   // Define our mesh representation to OpenCTM (store references to it in
+   // the context)
+   ctmDefineMesh(context, vertices, vertCount, indices, triCount, NULL);
+
+   // Save the OpenCTM file
+   ctmSave(context, "mymesh.ctm");
+
+   // Free the context
+   ctmFreeContext(context);
+
+   // Free our mesh
+   free(indices);
+   free(vertices);
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h.html new file mode 100644 index 000000000..d6711fceb --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h.html @@ -0,0 +1,1738 @@ + + + + +OpenCTM: openctm.h File Reference + + + + + + +
+

openctm.h File Reference

#include <stdint.h>
+ +

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Defines

#define CTM_API_VERSION   0x00000100
 OpenCTM API version (1.0).
#define CTM_TRUE   1
 Boolean TRUE.
#define CTM_FALSE   0
 Boolean FALSE.

Typedefs

typedef float CTMfloat
 Single precision floating point type (IEEE 754 32 bits wide).
typedef int32_t CTMint
 Signed integer (32 bits wide).
typedef uint32_t CTMuint
 Unsigned integer (32 bits wide).
typedef void * CTMcontext
 OpenCTM context handle.
typedef CTMuint(CTMCALL * CTMreadfn )(void *aBuf, CTMuint aCount, void *aUserData)
 Stream read() function pointer.
typedef CTMuint(CTMCALL * CTMwritefn )(const void *aBuf, CTMuint aCount, void *aUserData)
 Stream write() function pointer.

Enumerations

enum  CTMenum {
+  CTM_NONE = 0x0000, +
+  CTM_INVALID_CONTEXT = 0x0001, +
+  CTM_INVALID_ARGUMENT = 0x0002, +
+  CTM_INVALID_OPERATION = 0x0003, +
+  CTM_INVALID_MESH = 0x0004, +
+  CTM_OUT_OF_MEMORY = 0x0005, +
+  CTM_FILE_ERROR = 0x0006, +
+  CTM_BAD_FORMAT = 0x0007, +
+  CTM_LZMA_ERROR = 0x0008, +
+  CTM_INTERNAL_ERROR = 0x0009, +
+  CTM_UNSUPPORTED_FORMAT_VERSION = 0x000A, +
+  CTM_IMPORT = 0x0101, +
+  CTM_EXPORT = 0x0102, +
+  CTM_METHOD_RAW = 0x0201, +
+  CTM_METHOD_MG1 = 0x0202, +
+  CTM_METHOD_MG2 = 0x0203, +
+  CTM_VERTEX_COUNT = 0x0301, +
+  CTM_TRIANGLE_COUNT = 0x0302, +
+  CTM_HAS_NORMALS = 0x0303, +
+  CTM_UV_MAP_COUNT = 0x0304, +
+  CTM_ATTRIB_MAP_COUNT = 0x0305, +
+  CTM_VERTEX_PRECISION = 0x0306, +
+  CTM_NORMAL_PRECISION = 0x0307, +
+  CTM_COMPRESSION_METHOD = 0x0308, +
+  CTM_FILE_COMMENT = 0x0309, +
+  CTM_NAME = 0x0501, +
+  CTM_FILE_NAME = 0x0502, +
+  CTM_PRECISION = 0x0503, +
+  CTM_INDICES = 0x0601, +
+  CTM_VERTICES = 0x0602, +
+  CTM_NORMALS = 0x0603, +
+  CTM_UV_MAP_1 = 0x0700, +
+  CTM_UV_MAP_2 = 0x0701, +
+  CTM_UV_MAP_3 = 0x0702, +
+  CTM_UV_MAP_4 = 0x0703, +
+  CTM_UV_MAP_5 = 0x0704, +
+  CTM_UV_MAP_6 = 0x0705, +
+  CTM_UV_MAP_7 = 0x0706, +
+  CTM_UV_MAP_8 = 0x0707, +
+  CTM_ATTRIB_MAP_1 = 0x0800, +
+  CTM_ATTRIB_MAP_2 = 0x0801, +
+  CTM_ATTRIB_MAP_3 = 0x0802, +
+  CTM_ATTRIB_MAP_4 = 0x0803, +
+  CTM_ATTRIB_MAP_5 = 0x0804, +
+  CTM_ATTRIB_MAP_6 = 0x0805, +
+  CTM_ATTRIB_MAP_7 = 0x0806, +
+  CTM_ATTRIB_MAP_8 = 0x0807 +
+ }
 

OpenCTM specific enumerators.

+ More...

Functions

CTMEXPORT CTMcontext CTMCALL ctmNewContext (CTMenum aMode)
 Create a new OpenCTM context.
CTMEXPORT void CTMCALL ctmFreeContext (CTMcontext aContext)
 Free an OpenCTM context.
CTMEXPORT CTMenum CTMCALL ctmGetError (CTMcontext aContext)
 Returns the latest error.
CTMEXPORT const char *CTMCALL ctmErrorString (CTMenum aError)
 Converts an OpenCTM error code to a zero-terminated string.
CTMEXPORT CTMuint CTMCALL ctmGetInteger (CTMcontext aContext, CTMenum aProperty)
 Get information about an OpenCTM context.
CTMEXPORT CTMfloat CTMCALL ctmGetFloat (CTMcontext aContext, CTMenum aProperty)
 Get information about an OpenCTM context.
CTMEXPORT const CTMuint *CTMCALL ctmGetIntegerArray (CTMcontext aContext, CTMenum aProperty)
 Get an integer array from an OpenCTM context.
CTMEXPORT const CTMfloat *CTMCALL ctmGetFloatArray (CTMcontext aContext, CTMenum aProperty)
 Get a floating point array from an OpenCTM context.
CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap (CTMcontext aContext, const char *aName)
 Get a reference to the named UV map.
CTMEXPORT const char *CTMCALL ctmGetUVMapString (CTMcontext aContext, CTMenum aUVMap, CTMenum aProperty)
 Get information about a UV map.
CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat (CTMcontext aContext, CTMenum aUVMap, CTMenum aProperty)
 Get information about a UV map.
CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap (CTMcontext aContext, const char *aName)
 Get a reference to the named vertex attribute map.
CTMEXPORT const char *CTMCALL ctmGetAttribMapString (CTMcontext aContext, CTMenum aAttribMap, CTMenum aProperty)
 Get information about a vertex attribute map.
CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat (CTMcontext aContext, CTMenum aAttribMap, CTMenum aProperty)
 Get information about a vertex attribute map.
CTMEXPORT const char *CTMCALL ctmGetString (CTMcontext aContext, CTMenum aProperty)
 Get information about an OpenCTM context.
CTMEXPORT void CTMCALL ctmCompressionMethod (CTMcontext aContext, CTMenum aMethod)
 Set which compression method to use for the given OpenCTM context.
CTMEXPORT void CTMCALL ctmCompressionLevel (CTMcontext aContext, CTMuint aLevel)
 Set which LZMA compression level to use for the given OpenCTM context.
CTMEXPORT void CTMCALL ctmVertexPrecision (CTMcontext aContext, CTMfloat aPrecision)
 Set the vertex coordinate precision (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmVertexPrecisionRel (CTMcontext aContext, CTMfloat aRelPrecision)
 Set the vertex coordinate precision, relative to the mesh dimensions (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmNormalPrecision (CTMcontext aContext, CTMfloat aPrecision)
 Set the normal precision (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmUVCoordPrecision (CTMcontext aContext, CTMenum aUVMap, CTMfloat aPrecision)
 Set the coordinate precision for the specified UV map (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmAttribPrecision (CTMcontext aContext, CTMenum aAttribMap, CTMfloat aPrecision)
 Set the attribute value precision for the specified attribute map (only used by the MG2 compression method).
CTMEXPORT void CTMCALL ctmFileComment (CTMcontext aContext, const char *aFileComment)
 Set the file comment for the given OpenCTM context.
CTMEXPORT void CTMCALL ctmDefineMesh (CTMcontext aContext, const CTMfloat *aVertices, CTMuint aVertexCount, const CTMuint *aIndices, CTMuint aTriangleCount, const CTMfloat *aNormals)
 Define a triangle mesh.
CTMEXPORT CTMenum CTMCALL ctmAddUVMap (CTMcontext aContext, const CTMfloat *aUVCoords, const char *aName, const char *aFileName)
 Define a UV map.
CTMEXPORT CTMenum CTMCALL ctmAddAttribMap (CTMcontext aContext, const CTMfloat *aAttribValues, const char *aName)
 Define a custom vertex attribute map.
CTMEXPORT void CTMCALL ctmLoad (CTMcontext aContext, const char *aFileName)
 Load an OpenCTM format file into the context.
CTMEXPORT void CTMCALL ctmLoadCustom (CTMcontext aContext, CTMreadfn aReadFn, void *aUserData)
 Load an OpenCTM format file using a custom stream read function.
CTMEXPORT void CTMCALL ctmSave (CTMcontext aContext, const char *aFileName)
 Save an OpenCTM format file.
CTMEXPORT void CTMCALL ctmSaveCustom (CTMcontext aContext, CTMwritefn aWriteFn, void *aUserData)
 Save an OpenCTM format file using a custom stream write function.
+

Define Documentation

+ +
+
+ + + + +
#define CTM_API_VERSION   0x00000100
+
+
+ +

OpenCTM API version (1.0).

+ +
+
+ +
+
+ + + + +
#define CTM_FALSE   0
+
+
+ +

Boolean FALSE.

+ +
+
+ +
+
+ + + + +
#define CTM_TRUE   1
+
+
+ +

Boolean TRUE.

+ +
+
+

Typedef Documentation

+ +
+
+ + + + +
typedef void* CTMcontext
+
+
+ +

OpenCTM context handle.

+ +
+
+ +
+
+ + + + +
typedef float CTMfloat
+
+
+ +

Single precision floating point type (IEEE 754 32 bits wide).

+ +
+
+ +
+
+ + + + +
typedef int32_t CTMint
+
+
+ +

Signed integer (32 bits wide).

+ +
+
+ +
+
+ + + + +
typedef CTMuint(CTMCALL * CTMreadfn)(void *aBuf, CTMuint aCount, void *aUserData)
+
+
+ +

Stream read() function pointer.

+
Parameters:
+ + + + +
[in] aBuf Pointer to the memory buffer to which data should be read.
[in] aCount The number of bytes to read.
[in] aUserData The custom user data that was passed to the ctmLoadCustom() function.
+
+
+
Returns:
The number of bytes actually read (if this is less than aCount, it indicates that an error occured or the end of file was reached before all bytes were read).
+ +
+
+ +
+
+ + + + +
typedef uint32_t CTMuint
+
+
+ +

Unsigned integer (32 bits wide).

+ +
+
+ +
+
+ + + + +
typedef CTMuint(CTMCALL * CTMwritefn)(const void *aBuf, CTMuint aCount, void *aUserData)
+
+
+ +

Stream write() function pointer.

+
Parameters:
+ + + + +
[in] aBuf Pointer to the memory buffer from which data should be written.
[in] aCount The number of bytes to write.
[in] aUserData The custom user data that was passed to the ctmSaveCustom() function.
+
+
+
Returns:
The number of bytes actually written (if this is less than aCount, it indicates that an error occured).
+ +
+
+

Enumeration Type Documentation

+ +
+
+ + + + +
enum CTMenum
+
+
+ +

OpenCTM specific enumerators.

+
Note:
For the information query functions, it is an error to query a value of the wrong type (e.g. to query a string value with the ctmGetInteger() function).
+
Enumerator:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CTM_NONE  +

No error has occured (everything is OK).

+

Also used as an error return value for functions that should return a CTMenum value.

+
CTM_INVALID_CONTEXT  +

The OpenCTM context was invalid (e.g. NULL).

+
CTM_INVALID_ARGUMENT  +

A function argument was invalid.

+
CTM_INVALID_OPERATION  +

The operation is not allowed.

+
CTM_INVALID_MESH  +

The mesh was invalid (e.g. no vertices).

+
CTM_OUT_OF_MEMORY  +

Not enough memory to proceed.

+
CTM_FILE_ERROR  +

File I/O error.

+
CTM_BAD_FORMAT  +

File format error (e.g. unrecognized format or corrupted file).

+
CTM_LZMA_ERROR  +

An error occured within the LZMA library.

+
CTM_INTERNAL_ERROR  +

An internal error occured (indicates a bug).

+
CTM_UNSUPPORTED_FORMAT_VERSION  +

Unsupported file format version.

+
CTM_IMPORT  +

The OpenCTM context will be used for importing data.

+
CTM_EXPORT  +

The OpenCTM context will be used for exporting data.

+
CTM_METHOD_RAW  +

Just store the raw data.

+
CTM_METHOD_MG1  +

Lossless compression (floating point).

+
CTM_METHOD_MG2  +

Lossless compression (fixed point).

+
CTM_VERTEX_COUNT  +

Number of vertices in the mesh (integer).

+
CTM_TRIANGLE_COUNT  +

Number of triangles in the mesh (integer).

+
CTM_HAS_NORMALS  +

CTM_TRUE if the mesh has normals (integer).

+
CTM_UV_MAP_COUNT  +

Number of UV coordinate sets (integer).

+
CTM_ATTRIB_MAP_COUNT  +

Number of custom attribute sets (integer).

+
CTM_VERTEX_PRECISION  +

Vertex precision - for MG2 (float).

+
CTM_NORMAL_PRECISION  +

Normal precision - for MG2 (float).

+
CTM_COMPRESSION_METHOD  +

Compression method (integer).

+
CTM_FILE_COMMENT  +

File comment (string).

+
CTM_NAME  +

Unique name (UV/attrib map string).

+
CTM_FILE_NAME  +

File name reference (UV map string).

+
CTM_PRECISION  +

Value precision (UV/attrib map float).

+
CTM_INDICES  +

Triangle indices (integer array).

+
CTM_VERTICES  +

Vertex point coordinates (float array).

+
CTM_NORMALS  +

Per vertex normals (float array).

+
CTM_UV_MAP_1  +

Per vertex UV map 1 (float array).

+
CTM_UV_MAP_2  +

Per vertex UV map 2 (float array).

+
CTM_UV_MAP_3  +

Per vertex UV map 3 (float array).

+
CTM_UV_MAP_4  +

Per vertex UV map 4 (float array).

+
CTM_UV_MAP_5  +

Per vertex UV map 5 (float array).

+
CTM_UV_MAP_6  +

Per vertex UV map 6 (float array).

+
CTM_UV_MAP_7  +

Per vertex UV map 7 (float array).

+
CTM_UV_MAP_8  +

Per vertex UV map 8 (float array).

+
CTM_ATTRIB_MAP_1  +

Per vertex attribute map 1 (float array).

+
CTM_ATTRIB_MAP_2  +

Per vertex attribute map 2 (float array).

+
CTM_ATTRIB_MAP_3  +

Per vertex attribute map 3 (float array).

+
CTM_ATTRIB_MAP_4  +

Per vertex attribute map 4 (float array).

+
CTM_ATTRIB_MAP_5  +

Per vertex attribute map 5 (float array).

+
CTM_ATTRIB_MAP_6  +

Per vertex attribute map 6 (float array).

+
CTM_ATTRIB_MAP_7  +

Per vertex attribute map 7 (float array).

+
CTM_ATTRIB_MAP_8  +

Per vertex attribute map 8 (float array).

+
+
+
+ +
+
+

Function Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMenum CTMCALL ctmAddAttribMap (CTMcontext  aContext,
const CTMfloat aAttribValues,
const char *  aName 
)
+
+
+ +

Define a custom vertex attribute map.

+

Custom vertex attributes can be used for defining special per-vertex attributes, such as color, weight, ambient occlusion factor, etc.

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribValues An array of attribute values. Each attribute value is made up by four consecutive floats, and there must be as many values as there are vertices in the mesh.
[in] aName A unique name for this attribute map (zero terminated UTF-8 string).
+
+
+
Returns:
A attribute map index (CTM_ATTRIB_MAP_1 and higher). If the function failed, it will return the zero valued CTM_NONE (use ctmGetError() to determine the cause of the error).
+
Note:
A triangle mesh must have been defined before calling this function, since the number of vertices is defined by the triangle mesh.
+
See also:
ctmDefineMesh().
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMenum CTMCALL ctmAddUVMap (CTMcontext  aContext,
const CTMfloat aUVCoords,
const char *  aName,
const char *  aFileName 
)
+
+
+ +

Define a UV map.

+

There can be several UV maps in a mesh. A UV map is typically used for 2D texture mapping.

+
Parameters:
+ + + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVCoords An array of UV coordinates. Each UV coordinate is made up by two consecutive floats, and there must be as many coordinates as there are vertices in the mesh.
[in] aName A unique name for this UV map (zero terminated UTF-8 string).
[in] aFileName A reference to a image file (zero terminated UTF-8 string). If no file name reference exists, pass NULL.
+
+
+
Returns:
A UV map index (CTM_UV_MAP_1 and higher). If the function failed, it will return the zero valued CTM_NONE (use ctmGetError() to determine the cause of the error).
+
Note:
A triangle mesh must have been defined before calling this function, since the number of vertices is defined by the triangle mesh.
+
See also:
ctmDefineMesh().
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmAttribPrecision (CTMcontext  aContext,
CTMenum  aAttribMap,
CTMfloat  aPrecision 
)
+
+
+ +

Set the attribute value precision for the specified attribute map (only used by the MG2 compression method).

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribMap An attribute map specifier for a defined attribute map (CTM_ATTRIB_MAP_1, ...).
[in] aPrecision Fixed point precision. For instance, if this value is 0.001, all attribute values will be rounded to three decimals. If the attributes represent integer values, set the precision to 1.0. The default attribute precision is 2^-8 ~= 0.0039.
+
+
+
See also:
ctmAddAttribMap().
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmCompressionLevel (CTMcontext  aContext,
CTMuint  aLevel 
)
+
+
+ +

Set which LZMA compression level to use for the given OpenCTM context.

+

The compression level can be between 0 (fastest) and 9 (best). The higher the compression level, the more memory is required for compression and decompression. The default compression level is 1.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aLevel Which compression level to use (0 to 9).
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmCompressionMethod (CTMcontext  aContext,
CTMenum  aMethod 
)
+
+
+ +

Set which compression method to use for the given OpenCTM context.

+

The selected compression method will be used when calling the ctmSave() function.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aMethod Which compression method to use: CTM_METHOD_RAW, CTM_METHOD_MG1 or CTM_METHOD_MG2 (the default method is CTM_METHOD_MG1).
+
+
+
See also:
CTM_METHOD_RAW, CTM_METHOD_MG1, CTM_METHOD_MG2
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmDefineMesh (CTMcontext  aContext,
const CTMfloat aVertices,
CTMuint  aVertexCount,
const CTMuint aIndices,
CTMuint  aTriangleCount,
const CTMfloat aNormals 
)
+
+
+ +

Define a triangle mesh.

+
Parameters:
+ + + + + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aVertices An array of vertices (three consecutive floats make one vertex).
[in] aVertexCount The number of vertices in aVertices (and optionally aTexCoords).
[in] aIndices An array of vertex indices (three consecutive integers make one triangle).
[in] aTriangleCount The number of triangles in aIndices (there must be exactly 3 x aTriangleCount indices in aIndices).
[in] aNormals An array of per-vertex normals (or NULL if there are no normals). Each normal is made up by three consecutive floats, and there must be aVertexCount normals.
+
+
+
See also:
ctmAddUVMap(), ctmAddAttribMap(), ctmSave(), ctmSaveCustom().
+ +
+
+ +
+
+ + + + + + + + + +
CTMEXPORT const char* CTMCALL ctmErrorString (CTMenum  aError ) 
+
+
+ +

Converts an OpenCTM error code to a zero-terminated string.

+
Parameters:
+ + +
[in] aError An OpenCTM error code, as returned by ctmGetError().
+
+
+
Returns:
A zero terminated string that describes the error. For instance, if aError is CTM_INVALID_OPERATION, then the return value will be "CTM_INVALID_OPERATION".
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmFileComment (CTMcontext  aContext,
const char *  aFileComment 
)
+
+
+ +

Set the file comment for the given OpenCTM context.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aFileComment The file comment (zero terminated UTF-8 string).
+
+
+ +
+
+ +
+
+ + + + + + + + + +
CTMEXPORT void CTMCALL ctmFreeContext (CTMcontext  aContext ) 
+
+
+ +

Free an OpenCTM context.

+
Parameters:
+ + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
+
+
+
See also:
ctmNewContext()
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat (CTMcontext  aContext,
CTMenum  aAttribMap,
CTMenum  aProperty 
)
+
+
+ +

Get information about a vertex attribute map.

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 or higher).
[in] aProperty Which vertex attribute map property to return.
+
+
+
Returns:
A floating point value, representing the vertex attribute map property given by aProperty.
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT const char* CTMCALL ctmGetAttribMapString (CTMcontext  aContext,
CTMenum  aAttribMap,
CTMenum  aProperty 
)
+
+
+ +

Get information about a vertex attribute map.

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 or higher).
[in] aProperty Which vertex attribute map property to return.
+
+
+
Returns:
A string value, representing the vertex attribute map property given by aProperty.
+
Note:
The string is only valid as long as the vertex attribute map within the OpenCTM context is valid. Trying to access an invalid string will result in undefined behaviour. Therefor it is recommended that the string is copied to a new variable if it is to be used other than directly after the call to ctmGetAttribMapString().
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + +
CTMEXPORT CTMenum CTMCALL ctmGetError (CTMcontext  aContext ) 
+
+
+ +

Returns the latest error.

+

Calling this function will return the last produced error code, or CTM_NO_ERROR (zero) if no error has occured since the last call to ctmGetError(). When this function is called, the internal error varibale will be reset to CTM_NONE.

+
Parameters:
+ + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
+
+
+
Returns:
An OpenCTM error code.
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMfloat CTMCALL ctmGetFloat (CTMcontext  aContext,
CTMenum  aProperty 
)
+
+
+ +

Get information about an OpenCTM context.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which property to return.
+
+
+
Returns:
A floating point value, representing the OpenCTM context property given by aProperty.
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT const CTMfloat* CTMCALL ctmGetFloatArray (CTMcontext  aContext,
CTMenum  aProperty 
)
+
+
+ +

Get a floating point array from an OpenCTM context.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which array to return.
+
+
+
Returns:
A floating point array. If the requested array does not exist, or if aProperty does not indicate a float array, the function returns NULL.
+
Note:
The array is only valid as long as the OpenCTM context is valid, or until the corresponding array changes within the OpenCTM context. Trying to access an invalid array will result in undefined behaviour. Therefor it is recommended that the array is copied to a new variable if it is to be used other than directly after the call to ctmGetFloatArray().
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMuint CTMCALL ctmGetInteger (CTMcontext  aContext,
CTMenum  aProperty 
)
+
+
+ +

Get information about an OpenCTM context.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which property to return.
+
+
+
Returns:
An integer value, representing the OpenCTM context property given by aProperty.
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT const CTMuint* CTMCALL ctmGetIntegerArray (CTMcontext  aContext,
CTMenum  aProperty 
)
+
+
+ +

Get an integer array from an OpenCTM context.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which array to return.
+
+
+
Returns:
An integer array. If the requested array does not exist, or if aProperty does not indicate an integer array, the function returns NULL.
+
Note:
The array is only valid as long as the OpenCTM context is valid, or until the corresponding array changes within the OpenCTM context. Trying to access an invalid array will result in undefined behaviour. Therefor it is recommended that the array is copied to a new variable if it is to be used other than directly after the call to ctmGetIntegerArray().
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap (CTMcontext  aContext,
const char *  aName 
)
+
+
+ +

Get a reference to the named vertex attribute map.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aName The name of the attribute map that should be returned.
+
+
+
Returns:
A reference to an attribute map. If the attribute map was found, a value of CTM_ATTRIB_MAP_1 or higher is returned, otherwise CTM_NONE is returned.
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap (CTMcontext  aContext,
const char *  aName 
)
+
+
+ +

Get a reference to the named UV map.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aName The name of the UV map that should be returned.
+
+
+
Returns:
A reference to a UV map. If the UV map was found, a value of CTM_UV_MAP_1 or higher is returned, otherwise CTM_NONE is returned.
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT const char* CTMCALL ctmGetString (CTMcontext  aContext,
CTMenum  aProperty 
)
+
+
+ +

Get information about an OpenCTM context.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aProperty Which property to return.
+
+
+
Returns:
A string value, representing the OpenCTM context property given by aProperty.
+
Note:
The string is only valid as long as the OpenCTM context is valid, or until the corresponding string changes within the OpenCTM context (e.g. calling ctmFileComment() invalidates the CTM_FILE_COMMENT string). Trying to access an invalid string will result in undefined behaviour. Therefor it is recommended that the string is copied to a new variable if it is to be used other than directly after the call to ctmGetString().
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat (CTMcontext  aContext,
CTMenum  aUVMap,
CTMenum  aProperty 
)
+
+
+ +

Get information about a UV map.

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher).
[in] aProperty Which UV map property to return.
+
+
+
Returns:
A floating point value, representing the UV map property given by aProperty.
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT const char* CTMCALL ctmGetUVMapString (CTMcontext  aContext,
CTMenum  aUVMap,
CTMenum  aProperty 
)
+
+
+ +

Get information about a UV map.

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher).
[in] aProperty Which UV map property to return.
+
+
+
Returns:
A string value, representing the UV map property given by aProperty.
+
Note:
The string is only valid as long as the UV map within the OpenCTM context is valid. Trying to access an invalid string will result in undefined behaviour. Therefor it is recommended that the string is copied to a new variable if it is to be used other than directly after the call to ctmGetUVMapString().
+
See also:
CTMenum
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmLoad (CTMcontext  aContext,
const char *  aFileName 
)
+
+
+ +

Load an OpenCTM format file into the context.

+

The mesh data can be retrieved with the various ctmGet functions.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aFileName The name of the file to be loaded.
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmLoadCustom (CTMcontext  aContext,
CTMreadfn  aReadFn,
void *  aUserData 
)
+
+
+ +

Load an OpenCTM format file using a custom stream read function.

+

The mesh data can be retrieved with the various ctmGet functions.

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aReadFn Pointer to a custom stream read function.
[in] aUserData Custom user data, which can be a C language FILE handle, C++ istream object, or a custom object pointer of any type. The user data pointer will be passed to the custom stream read function.
+
+
+
See also:
CTMreadfn.
+ +
+
+ +
+
+ + + + + + + + + +
CTMEXPORT CTMcontext CTMCALL ctmNewContext (CTMenum  aMode ) 
+
+
+ +

Create a new OpenCTM context.

+

The context is used for all subsequent OpenCTM function calls. Several contexts can coexist at the same time.

+
Parameters:
+ + +
[in] aMode An OpenCTM context mode. Set this to CTM_IMPORT if the context will be used for importing data, or set it to CTM_EXPORT if it will be used for exporting data.
+
+
+
Returns:
An OpenCTM context handle (or NULL if no context could be created).
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmNormalPrecision (CTMcontext  aContext,
CTMfloat  aPrecision 
)
+
+
+ +

Set the normal precision (only used by the MG2 compression method).

+

The normal is represented in spherical coordinates in the MG2 compression method, and the normal precision controls the angular and radial resolution.

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aPrecision Fixed point precision. For the angular information, this value represents the angular precision. For the radial information, this value is the linear resolution. For instance, 0.01 means that the circle is divided into 100 steps, and the normal magnitude is rounded to 2 decimals. The default normal precision is 2^-8 ~= 0.0039.
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmSave (CTMcontext  aContext,
const char *  aFileName 
)
+
+
+ +

Save an OpenCTM format file.

+

The mesh must have been defined by ctmDefineMesh().

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aFileName The name of the file to be saved.
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmSaveCustom (CTMcontext  aContext,
CTMwritefn  aWriteFn,
void *  aUserData 
)
+
+
+ +

Save an OpenCTM format file using a custom stream write function.

+

The mesh must have been defined by ctmDefineMesh().

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aWriteFn Pointer to a custom stream write function.
[in] aUserData Custom user data, which can be a C language FILE handle, C++ ostream object, or a custom object pointer of any type. The user data pointer will be passed to the custom stream write function.
+
+
+
See also:
CTMwritefn.
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmUVCoordPrecision (CTMcontext  aContext,
CTMenum  aUVMap,
CTMfloat  aPrecision 
)
+
+
+ +

Set the coordinate precision for the specified UV map (only used by the MG2 compression method).

+
Parameters:
+ + + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aUVMap A UV map specifier for a defined UV map (CTM_UV_MAP_1, ...).
[in] aPrecision Fixed point precision. For instance, if this value is 0.001, all UV coordinates will be rounded to three decimals. The default UV coordinate precision is 2^-12 ~= 0.00024.
+
+
+
See also:
ctmAddUVMap().
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmVertexPrecision (CTMcontext  aContext,
CTMfloat  aPrecision 
)
+
+
+ +

Set the vertex coordinate precision (only used by the MG2 compression method).

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aPrecision Fixed point precision. For instance, if this value is 0.001, all vertex coordinates will be rounded to three decimals. The default vertex coordinate precision is 2^-10 ~= 0.00098.
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
CTMEXPORT void CTMCALL ctmVertexPrecisionRel (CTMcontext  aContext,
CTMfloat  aRelPrecision 
)
+
+
+ +

Set the vertex coordinate precision, relative to the mesh dimensions (only used by the MG2 compression method).

+
Parameters:
+ + + +
[in] aContext An OpenCTM context that has been created by ctmNewContext().
[in] aRelPrecision Relative precision. This factor is multiplied by the average triangle edge length in the mesh in order to obtain the final, fixed point precision. For instance, if aRelPrecision is 0.01, and the average edge length is 3.7, then the fixed point precision is set to 0.037.
+
+
+
Note:
The mesh must have been defined using the ctmDefineMesh() function before calling this function.
+
See also:
ctmVertexPrecision().
+ +
+
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h_source.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h_source.html new file mode 100644 index 000000000..740225adf --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/openctm_8h_source.html @@ -0,0 +1,287 @@ + + + + +OpenCTM: openctm.h Source File + + + + + + +
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h.html new file mode 100644 index 000000000..fc52a74d6 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h.html @@ -0,0 +1,46 @@ + + + + +OpenCTM: openctmpp.h File Reference + + + + + + +
+

openctmpp.h File Reference

#include "openctm.h"
+#include <exception>
+ +

Go to the source code of this file.

+ + + + + + + + +

Classes

class  ctm_error
 OpenCTM exception. More...
class  CTMimporter
 OpenCTM importer class. More...
class  CTMexporter
 OpenCTM exporter class. More...
+
+
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h_source.html b/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h_source.html new file mode 100644 index 000000000..24c8c2703 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/openctmpp_8h_source.html @@ -0,0 +1,333 @@ + + + + +OpenCTM: openctmpp.h Source File + + + + + + +
+

Copyright © 2009-2010 Marcus Geelnard — + openctm.sourceforge.net

+
+ + diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_b.gif b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_b.gif new file mode 100644 index 000000000..0d623483f Binary files /dev/null and b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_b.gif differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_l.gif b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_l.gif new file mode 100644 index 000000000..9b1e6337c Binary files /dev/null and b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_l.gif differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tab_r.gif b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_r.gif new file mode 100644 index 000000000..ce9dd9f53 Binary files /dev/null and b/src/external/OpenCTM-1.0.3/doc/APIReference/tab_r.gif differ diff --git a/src/external/OpenCTM-1.0.3/doc/APIReference/tabs.css b/src/external/OpenCTM-1.0.3/doc/APIReference/tabs.css new file mode 100644 index 000000000..a44416341 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/APIReference/tabs.css @@ -0,0 +1,105 @@ +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; +} + +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84B0C7; + font-size : 80%; + font-weight : bold; + text-decoration : none; +} + +DIV.tabs A:hover +{ + background-position: 100% -150px; +} + +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1A419D; +} + +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; +} + +DIV.tabs #MSearchBox +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : 80%; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; +} + +DIV.tabs LI.current A +{ + background-position: 100% -150px; + border-width : 0px; +} + +DIV.tabs LI.current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; +} + +DIV.navpath +{ + background : none; + border : none; + border-bottom : 1px solid #84B0C7; + text-align : center; + margin : 2px; + padding : 2px; +} diff --git a/src/external/OpenCTM-1.0.3/doc/DevelopersManual.pdf b/src/external/OpenCTM-1.0.3/doc/DevelopersManual.pdf new file mode 100644 index 000000000..d280b66f6 Binary files /dev/null and b/src/external/OpenCTM-1.0.3/doc/DevelopersManual.pdf differ diff --git a/src/external/OpenCTM-1.0.3/doc/FormatSpecification.pdf b/src/external/OpenCTM-1.0.3/doc/FormatSpecification.pdf new file mode 100644 index 000000000..fa8ce84c8 Binary files /dev/null and b/src/external/OpenCTM-1.0.3/doc/FormatSpecification.pdf differ diff --git a/src/external/OpenCTM-1.0.3/doc/ctmconv.1 b/src/external/OpenCTM-1.0.3/doc/ctmconv.1 new file mode 100644 index 000000000..ad76f0745 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/ctmconv.1 @@ -0,0 +1,92 @@ +.TH ctmconv 1 +.SH NAME +.B ctmconv +- file format converter for 3D models +.SH SYNOPSIS +.B ctmconv +.I infile outfile [options] +.SH DESCRIPTION +.B ctmconv +is a 3D file converter that can convert 3D model files to and from several +different formats. +.PP +The file +.I infile +is loaded, and then saved as +.I outfile +in the target file format. +.PP +The input and output file formats are determined from the file endings. +.SH OPTIONS +The following options are available: +.TP 16 +.B --scale arg +Scale the mesh by a scalar factor. +.TP +.B --upaxis arg +Set up axis (X, Y, Z, -X, -Y, -Z). If != Z, the mesh will be flipped. +.TP +.B --flip +Flip triangle orientation. +.TP +.B --calc-normals +If the source file does not contain any normals, calculate them. +.TP +.B --no-normals +Do not export normals. +.TP +.B --no-texcoords +Do not export texture coordinates. +.TP +.B --no-colors +Do not export vertex colors. +.TP +.B --comment arg +Set the file comment (default is to use the comment from the input file, if +any). +.TP +.B --texfile arg +Set the texture file name reference for the texture (default is to use the +texture file name reference from the input file, if any). +.PP +When exporting an OpenCTM file, the following options are also +available: +.TP 16 +.B --method arg +Select compression method (RAW, MG1, MG2). +.TP +.B --level arg +Set the compression level (0 - 9). +.TP +.B --vprec arg +Set vertex precision (only for MG2). +.TP +.B --vprecrel arg +Set vertex precision, relative method (only for MG2). +.TP +.B --nprec arg +Set normal precision (only for MG2). +.TP +.B --tprec arg +Set texture map precision (only for MG2). +.TP +.B --cprec arg +Set color precision (only for MG2). +.SH FILE FORMATS +The following 3D model file formats are supported: +OpenCTM (.ctm), +Stanford triangle format (.ply), +Stereolitography (.stl), +3D Studio (.3ds), +COLLADA 1.4/1.5 (.dae), +Wavefront geometry file (.obj), +LightWave object (.lwo), +Geomview object file format (.off), +VRML 2.0 - export only (.wrl). +.SH AVAILABILITY +.B ctmconv +is designed to be portable, and is available for several different systems, +including (but not limited to): Windows, Mac OS X (10.3+), Linux and +OpenSolaris. +.SH SEE ALSO +ctmviewer(1) diff --git a/src/external/OpenCTM-1.0.3/doc/ctmviewer.1 b/src/external/OpenCTM-1.0.3/doc/ctmviewer.1 new file mode 100644 index 000000000..d06dce48d --- /dev/null +++ b/src/external/OpenCTM-1.0.3/doc/ctmviewer.1 @@ -0,0 +1,86 @@ +.TH ctmviewer 1 +.SH NAME +.B ctmviewer +- 3D viewer for models of various file formats +.SH SYNOPSIS +.B ctmviewer +.I [modelfile [texturefile]] +.SH DESCRIPTION +.B ctmviewer +is a 3D file viewer that can load, show and save 3D model files in several +different formats. +.PP +The program displays an interactive 3D view of the model, which can be operated +with the mouse (e.g. for rotating and zooming). +.PP +If the selected model file contains texture coordinate information, it is +possible to specify which 2D image file to use as a texture with the additional +.I texturefile +argument. If no texture file is given (either by the 3D model file, or by the +.I texturefile +argument), a standard 2D grid is used as a texture. +.SH GUI OPERATIONS +In addition to the command line arguments, +.B ctmviewer +offers several operations that can be performed from the 3D GUI display. For +help, press the F1 key. +.SS Loading and Saving +It is possible to load and save 3D model files from the program by either +using the buttons in the upper left corner of the 3D display, or by using the +keyboard shortcuts CTRL+O (open) and CTRL+S (save). +.PP +It is also possible to load a texture file from the program by using the +Open Texture button. +.SS Rendering +To toggle between a normal filled surface view (default) and a wire frame view, +press the 'w' key. +.SS Camera Control +By holding down the left mouse button and moving the mouse, the camera is +rotated around the 3D model. +.PP +By holding down the right mouse button and moving the mouse, the camera will +pan left/right and up/down. +.PP +By holding down the middle mouse button and moving the mouse, the camera will +zoom in and out. It is also possible to use the mouse wheel (not supported on +all systems) or the +/- keys to zoom in and out. +.PP +Double click the left mouse button on a point on the model to focus the camera +on that point. +.PP +Press the 'f' key to fit the model into the screen view (re-center and re-zoom). +.PP +Press the 'y' key to change the camera up direction to the Y axis (may be +necessary if the model was designed in or for an environment where the Y axis +is considered the up direction). +.PP +Press the 'z' key to change the camera up direction to the Z axis (default). +.SH FILE FORMATS +The following 3D model file formats are supported: +OpenCTM (.ctm), +Stanford triangle format (.ply), +Stereolitography (.stl), +3D Studio (.3ds), +COLLADA 1.4/1.5 (.dae), +Wavefront geometry file (.obj), +LightWave object (.lwo), +Geomview object file format (.off), +VRML 2.0 - export only (.wrl). +.PP +The following 2D image file formats are supported (texture): +JPEG (.jpg), PNG (.png). +.SH AVAILABILITY +.B ctmviewer +is designed to be portable, and is available for several different systems, +including (but not limited to): Windows, Mac OS X (10.3+), Linux and +OpenSolaris. +.PP +.B ctmviewer +uses OpenGL for its accelerated 3D display. When the OpenGL implementation +supports it, +.B ctmviewer +will use per pixel Phong shading for improved visual appearance. Otherwise +.B ctmviewer +will fall back to classic per vertex shading. +.SH SEE ALSO +ctmconv(1) diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.linux b/src/external/OpenCTM-1.0.3/lib/Makefile.linux new file mode 100644 index 000000000..9e270e517 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/Makefile.linux @@ -0,0 +1,81 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.linux +# Description: Makefile for Linux systems (should work on most Un*x-like +# systems with gcc, e.g. OpenSolaris). +############################################################################### +# Copyright (c) 2009-2010 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +LZMADIR = liblzma +CC = gcc +CFLAGS = -O3 -W -Wall -c -fPIC -DOPENCTM_BUILD -I$(LZMADIR) -DLZMA_PREFIX_CTM -std=c99 -pedantic +CFLAGS_LZMA = -O3 -W -Wall -c -fPIC -DLZMA_PREFIX_CTM -std=c99 -pedantic +RM = rm -f +DEPEND = $(CPP) -MM + +DYNAMICLIB = libopenctm.so + +OBJS = openctm.o \ + stream.o \ + compressRAW.o \ + compressMG1.o \ + compressMG2.o + +LZMA_OBJS = Alloc.o \ + LzFind.o \ + LzmaDec.o \ + LzmaEnc.o \ + LzmaLib.o + +SRCS = openctm.c \ + stream.c \ + compressRAW.c \ + compressMG1.c \ + compressMG2.c + +LZMA_SRCS = $(LZMADIR)/Alloc.c \ + $(LZMADIR)/LzFind.c \ + $(LZMADIR)/LzmaDec.c \ + $(LZMADIR)/LzmaEnc.c \ + $(LZMADIR)/LzmaLib.c + +.phony: all clean depend + +all: $(DYNAMICLIB) + +clean: + $(RM) $(DYNAMICLIB) $(OBJS) $(LZMA_OBJS) + +$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) + gcc -shared -s -Wl,-soname,$@ -o $@ $(OBJS) $(LZMA_OBJS) -lm + +%.o: %.c + $(CC) $(CFLAGS) $< + +%.o: $(LZMADIR)/%.c + $(CC) $(CFLAGS_LZMA) $< + +depend: + $(DEPEND) $(SRCS) $(LZMA_SRCS) > make.depend + +-include make.depend diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.macosx b/src/external/OpenCTM-1.0.3/lib/Makefile.macosx new file mode 100644 index 000000000..d1685a0c6 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/Makefile.macosx @@ -0,0 +1,86 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.macosx +# Description: Makefile for Mac OS X. +############################################################################### +# Copyright (c) 2009-2010 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +LZMADIR = liblzma +CC = gcc +CFLAGS = -arch i386 -O3 -W -Wall -c -fvisibility=hidden -DOPENCTM_BUILD -I$(LZMADIR) -DLZMA_PREFIX_CTM -std=c99 -pedantic +CFLAGS_LZMA = -arch i386 -O3 -W -Wall -c -fvisibility=hidden -DLZMA_PREFIX_CTM -std=c99 -pedantic +RM = rm -f +DEPEND = $(CPP) -MM + +DYNAMICLIB = libopenctm.dylib +STATICLIB = libopenctm.a + + +OBJS = openctm.o \ + stream.o \ + compressRAW.o \ + compressMG1.o \ + compressMG2.o + +LZMA_OBJS = Alloc.o \ + LzFind.o \ + LzmaDec.o \ + LzmaEnc.o \ + LzmaLib.o + +SRCS = openctm.c \ + stream.c \ + compressRAW.c \ + compressMG1.c \ + compressMG2.c + +LZMA_SRCS = $(LZMADIR)/Alloc.c \ + $(LZMADIR)/LzFind.c \ + $(LZMADIR)/LzmaDec.c \ + $(LZMADIR)/LzmaEnc.c \ + $(LZMADIR)/LzmaLib.c + +.phony: all clean depend + +#all: $(DYNAMICLIB) +all: $(STATICLIB) + +clean: + $(RM) $(DYNAMICLIB) $(OBJS) $(LZMA_OBJS) + +$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) + gcc -dynamiclib -o $@ $(OBJS) $(LZMA_OBJS) + +$(STATICLIB): $(OBJS) $(LZMA_OBJS) + ar rcs $@ $(OBJS) $(LZMA_OBJS) + +%.o: %.c + $(CC) $(CFLAGS) $< + +%.o: $(LZMADIR)/%.c + $(CC) $(CFLAGS_LZMA) $< + +depend: + $(DEPEND) $(SRCS) $(LZMA_SRCS) > make.depend + +-include make.depend diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.mingw b/src/external/OpenCTM-1.0.3/lib/Makefile.mingw new file mode 100644 index 000000000..8606be77e --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/Makefile.mingw @@ -0,0 +1,87 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.mingw +# Description: Makefile for MinGW32 for Windows. +############################################################################### +# Copyright (c) 2009-2010 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +LZMADIR = liblzma +CC = gcc +CFLAGS = -O3 -W -Wall -c -DOPENCTM_BUILD -I$(LZMADIR) -DLZMA_PREFIX_CTM -std=c99 -pedantic +CFLAGS_LZMA = -O3 -W -Wall -c -DLZMA_PREFIX_CTM -std=c99 -pedantic +RM = del /Q +DEPEND = $(CC) -MM +RC = windres + +DYNAMICLIB = openctm.dll +LINKLIB = libopenctm.a + +OBJS = openctm.o \ + stream.o \ + compressRAW.o \ + compressMG1.o \ + compressMG2.o + +LZMA_OBJS = Alloc.o \ + LzFind.o \ + LzmaDec.o \ + LzmaEnc.o \ + LzmaLib.o + +SRCS = openctm.c \ + stream.c \ + compressRAW.c \ + compressMG1.c \ + compressMG2.c + +LZMA_SRCS = $(LZMADIR)/Alloc.c \ + $(LZMADIR)/LzFind.c \ + $(LZMADIR)/LzmaDec.c \ + $(LZMADIR)/LzmaEnc.c \ + $(LZMADIR)/LzmaLib.c + +.phony: all clean depend + +all: $(DYNAMICLIB) + +clean: + $(RM) $(DYNAMICLIB) $(LINKLIB) $(OBJS) $(LZMA_OBJS) openctm-res.o + +$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) openctm-mingw1.def openctm-mingw2.def openctm-res.o + dllwrap --def openctm-mingw1.def -o $@ $(OBJS) $(LZMA_OBJS) openctm-res.o + strip $@ + dlltool --kill-at --output-lib $(LINKLIB) --def openctm-mingw2.def + +openctm-res.o: openctm.rc + $(RC) $< $@ + +%.o: %.c + $(CC) $(CFLAGS) $< + +%.o: $(LZMADIR)/%.c + $(CC) $(CFLAGS_LZMA) $< + +depend: + $(DEPEND) $(SRCS) $(LZMA_SRCS) > make.depend + +-include make.depend diff --git a/src/external/OpenCTM-1.0.3/lib/Makefile.msvc b/src/external/OpenCTM-1.0.3/lib/Makefile.msvc new file mode 100644 index 000000000..70818d553 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/Makefile.msvc @@ -0,0 +1,103 @@ +############################################################################### +# Product: OpenCTM +# File: Makefile.msvc +# Description: Makefile for MS Visual Studio 2008 for Windows. +############################################################################### +# Copyright (c) 2009-2010 Marcus Geelnard +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not +# be misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +############################################################################### + +LZMADIR = liblzma +CC = cl +CFLAGS = /nologo /Ox /W3 /c /DOPENCTM_BUILD /I$(LZMADIR) /DLZMA_PREFIX_CTM /D_CRT_SECURE_NO_WARNINGS +CFLAGS_LZMA = /nologo /Ox /W3 /c /DLZMA_PREFIX_CTM +RM = del /Q +RC = rc + +DYNAMICLIB = openctm.dll +LINKLIB = openctm.lib + +OBJS = openctm.obj \ + stream.obj \ + compressRAW.obj \ + compressMG1.obj \ + compressMG2.obj + +LZMA_OBJS = Alloc.obj \ + LzFind.obj \ + LzmaDec.obj \ + LzmaEnc.obj \ + LzmaLib.obj + +SRCS = openctm.c \ + stream.c \ + compressRAW.c \ + compressMG1.c \ + compressMG2.c + +LZMA_SRCS = $(LZMADIR)\Alloc.c \ + $(LZMADIR)\LzFind.c \ + $(LZMADIR)\LzmaDec.c \ + $(LZMADIR)\LzmaEnc.c \ + $(LZMADIR)\LzmaLib.c + +all: $(DYNAMICLIB) + +.PHONY: clean + +clean: + $(RM) $(DYNAMICLIB) $(LINKLIB) $(OBJS) $(LZMA_OBJS) openctm.res + +$(DYNAMICLIB): $(OBJS) $(LZMA_OBJS) openctm-msvc.def openctm.res + link /nologo /out:$@ /dll /implib:$(LINKLIB) /def:openctm-msvc.def $(OBJS) $(LZMA_OBJS) openctm.res + +openctm.res: openctm.rc + $(RC) openctm.rc + +openctm.obj: openctm.c openctm.h internal.h + $(CC) $(CFLAGS) openctm.c + +stream.obj: stream.c openctm.h internal.h + $(CC) $(CFLAGS) stream.c + +compressRAW.obj: compressRAW.c openctm.h internal.h + $(CC) $(CFLAGS) compressRAW.c + +compressMG1.obj: compressMG1.c openctm.h internal.h + $(CC) $(CFLAGS) compressMG1.c + +compressMG2.obj: compressMG2.c openctm.h internal.h + $(CC) $(CFLAGS) compressMG2.c + +Alloc.obj: $(LZMADIR)\Alloc.c $(LZMADIR)\Alloc.h + $(CC) $(CFLAGS_LZMA) $(LZMADIR)\Alloc.c + +LzFind.obj: $(LZMADIR)\LzFind.c $(LZMADIR)\LzFind.h $(LZMADIR)\Types.h $(LZMADIR)\LzHash.h $(LZMADIR)\NameMangle.h + $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzFind.c + +LzmaDec.obj: $(LZMADIR)\LzmaDec.c $(LZMADIR)\LzmaDec.h $(LZMADIR)\Types.h $(LZMADIR)\NameMangle.h + $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzmaDec.c + +LzmaEnc.obj: $(LZMADIR)\LzmaEnc.c $(LZMADIR)\LzmaEnc.h $(LZMADIR)\Types.h $(LZMADIR)\LzFind.h $(LZMADIR)\NameMangle.h + $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzmaEnc.c + +LzmaLib.obj: $(LZMADIR)\LzmaLib.c $(LZMADIR)\LzmaEnc.h $(LZMADIR)\Types.h $(LZMADIR)\LzmaDec.h $(LZMADIR)\Alloc.h $(LZMADIR)\LzmaLib.h $(LZMADIR)\NameMangle.h + $(CC) $(CFLAGS_LZMA) $(LZMADIR)\LzmaLib.c diff --git a/src/external/OpenCTM-1.0.3/lib/compressMG1.c b/src/external/OpenCTM-1.0.3/lib/compressMG1.c new file mode 100644 index 000000000..e4ca1b747 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/compressMG1.c @@ -0,0 +1,324 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: compressMG1.c +// Description: Implementation of the MG1 compression method. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +#include +#include +#include "openctm.h" +#include "internal.h" + +#ifdef __DEBUG_ +#include +#endif + + +//----------------------------------------------------------------------------- +// _compareTriangle() - Comparator for the triangle sorting. +//----------------------------------------------------------------------------- +static int _compareTriangle(const void * elem1, const void * elem2) +{ + CTMuint * tri1 = (CTMuint *) elem1; + CTMuint * tri2 = (CTMuint *) elem2; + if(tri1[0] != tri2[0]) + return tri1[0] - tri2[0]; + else + return tri1[1] - tri2[1]; +} + +//----------------------------------------------------------------------------- +// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal +// compression. +//----------------------------------------------------------------------------- +static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices) +{ + CTMuint * tri, tmp, i; + + // Step 1: Make sure that the first index of each triangle is the smallest + // one (rotate triangle nodes if necessary) + for(i = 0; i < self->mTriangleCount; ++ i) + { + tri = &aIndices[i * 3]; + if((tri[1] < tri[0]) && (tri[1] < tri[2])) + { + tmp = tri[0]; + tri[0] = tri[1]; + tri[1] = tri[2]; + tri[2] = tmp; + } + else if((tri[2] < tri[0]) && (tri[2] < tri[1])) + { + tmp = tri[0]; + tri[0] = tri[2]; + tri[2] = tri[1]; + tri[1] = tmp; + } + } + + // Step 2: Sort the triangles based on the first triangle index + qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle); +} + +//----------------------------------------------------------------------------- +// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to +// reduce data entropy. +//----------------------------------------------------------------------------- +static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices) +{ + CTMint i; + for(i = self->mTriangleCount - 1; i >= 0; -- i) + { + // Step 1: Calculate delta from second triangle index to the previous + // second triangle index, if the previous triangle shares the same first + // index, otherwise calculate the delta to the first triangle index + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) + aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1]; + else + aIndices[i * 3 + 1] -= aIndices[i * 3]; + + // Step 2: Calculate delta from third triangle index to the first triangle + // index + aIndices[i * 3 + 2] -= aIndices[i * 3]; + + // Step 3: Calculate derivative of the first triangle index + if(i >= 1) + aIndices[i * 3] -= aIndices[(i - 1) * 3]; + } +} + +//----------------------------------------------------------------------------- +// _ctmRestoreIndices() - Restore original indices (inverse derivative +// operation). +//----------------------------------------------------------------------------- +static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices) +{ + CTMuint i; + + for(i = 0; i < self->mTriangleCount; ++ i) + { + // Step 1: Reverse derivative of the first triangle index + if(i >= 1) + aIndices[i * 3] += aIndices[(i - 1) * 3]; + + // Step 2: Reverse delta from third triangle index to the first triangle + // index + aIndices[i * 3 + 2] += aIndices[i * 3]; + + // Step 3: Reverse delta from second triangle index to the previous + // second triangle index, if the previous triangle shares the same first + // index, otherwise reverse the delta to the first triangle index + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) + aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1]; + else + aIndices[i * 3 + 1] += aIndices[i * 3]; + } +} + +//----------------------------------------------------------------------------- +// _ctmCompressMesh_MG1() - Compress the mesh that is stored in the CTM +// context, and write it the the output stream in the CTM context. +//----------------------------------------------------------------------------- +int _ctmCompressMesh_MG1(_CTMcontext * self) +{ + CTMuint * indices; + _CTMfloatmap * map; + CTMuint i; + +#ifdef __DEBUG_ + printf("COMPRESSION METHOD: MG1\n"); +#endif + + // Perpare (sort) indices + indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); + if(!indices) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + for(i = 0; i < self->mTriangleCount * 3; ++ i) + indices[i] = self->mIndices[i]; + _ctmReArrangeTriangles(self, indices); + + // Calculate index deltas (entropy-reduction) + _ctmMakeIndexDeltas(self, indices); + + // Write triangle indices +#ifdef __DEBUG_ + printf("Inidices: "); +#endif + _ctmStreamWrite(self, (void *) "INDX", 4); + if(!_ctmStreamWritePackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE)) + { + free((void *) indices); + return CTM_FALSE; + } + + // Free temporary resources + free((void *) indices); + + // Write vertices +#ifdef __DEBUG_ + printf("Vertices: "); +#endif + _ctmStreamWrite(self, (void *) "VERT", 4); + if(!_ctmStreamWritePackedFloats(self, self->mVertices, self->mVertexCount * 3, 1)) + { + free((void *) indices); + return CTM_FALSE; + } + + // Write normals + if(self->mNormals) + { +#ifdef __DEBUG_ + printf("Normals: "); +#endif + _ctmStreamWrite(self, (void *) "NORM", 4); + if(!_ctmStreamWritePackedFloats(self, self->mNormals, self->mVertexCount, 3)) + return CTM_FALSE; + } + + // Write UV maps + map = self->mUVMaps; + while(map) + { +#ifdef __DEBUG_ + printf("UV coordinates (%s): ", map->mName ? map->mName : "no name"); +#endif + _ctmStreamWrite(self, (void *) "TEXC", 4); + _ctmStreamWriteSTRING(self, map->mName); + _ctmStreamWriteSTRING(self, map->mFileName); + if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 2)) + return CTM_FALSE; + map = map->mNext; + } + + // Write attribute maps + map = self->mAttribMaps; + while(map) + { +#ifdef __DEBUG_ + printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name"); +#endif + _ctmStreamWrite(self, (void *) "ATTR", 4); + _ctmStreamWriteSTRING(self, map->mName); + if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 4)) + return CTM_FALSE; + map = map->mNext; + } + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _ctmUncompressMesh_MG1() - Uncmpress the mesh from the input stream in the +// CTM context, and store the resulting mesh in the CTM context. +//----------------------------------------------------------------------------- +int _ctmUncompressMesh_MG1(_CTMcontext * self) +{ + CTMuint * indices; + _CTMfloatmap * map; + CTMuint i; + + // Allocate memory for the indices + indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); + if(!indices) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Read triangle indices + if(_ctmStreamReadUINT(self) != FOURCC("INDX")) + { + self->mError = CTM_BAD_FORMAT; + free(indices); + return CTM_FALSE; + } + if(!_ctmStreamReadPackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE)) + return CTM_FALSE; + + // Restore indices + _ctmRestoreIndices(self, indices); + for(i = 0; i < self->mTriangleCount * 3; ++ i) + self->mIndices[i] = indices[i]; + + // Free temporary resources + free(indices); + + // Read vertices + if(_ctmStreamReadUINT(self) != FOURCC("VERT")) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + if(!_ctmStreamReadPackedFloats(self, self->mVertices, self->mVertexCount * 3, 1)) + return CTM_FALSE; + + // Read normals + if(self->mNormals) + { + if(_ctmStreamReadUINT(self) != FOURCC("NORM")) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + if(!_ctmStreamReadPackedFloats(self, self->mNormals, self->mVertexCount, 3)) + return CTM_FALSE; + } + + // Read UV maps + map = self->mUVMaps; + while(map) + { + if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) + { + self->mError = CTM_BAD_FORMAT; + return 0; + } + _ctmStreamReadSTRING(self, &map->mName); + _ctmStreamReadSTRING(self, &map->mFileName); + if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 2)) + return CTM_FALSE; + map = map->mNext; + } + + // Read vertex attribute maps + map = self->mAttribMaps; + while(map) + { + if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) + { + self->mError = CTM_BAD_FORMAT; + return 0; + } + _ctmStreamReadSTRING(self, &map->mName); + if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 4)) + return CTM_FALSE; + map = map->mNext; + } + + return CTM_TRUE; +} diff --git a/src/external/OpenCTM-1.0.3/lib/compressMG2.c b/src/external/OpenCTM-1.0.3/lib/compressMG2.c new file mode 100644 index 000000000..d993fef65 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/compressMG2.c @@ -0,0 +1,1319 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: compressMG2.c +// Description: Implementation of the MG2 compression method. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +#include +#include +#include "openctm.h" +#include "internal.h" + +#ifdef __DEBUG_ +#include +#endif + +// We need PI +#ifndef PI +#define PI 3.141592653589793238462643f +#endif + + +//----------------------------------------------------------------------------- +// _CTMgrid - 3D space subdivision grid. +//----------------------------------------------------------------------------- +typedef struct { + // Axis-aligned boudning box for the grid. + CTMfloat mMin[3]; + CTMfloat mMax[3]; + + // How many divisions per axis (minimum 1). + CTMuint mDivision[3]; + + // Size of each grid box. + CTMfloat mSize[3]; +} _CTMgrid; + +//----------------------------------------------------------------------------- +// _CTMsortvertex - Vertex information. +//----------------------------------------------------------------------------- +typedef struct { + // Vertex X coordinate (used for sorting). + CTMfloat x; + + // Grid index. This is the index into the 3D space subdivision grid. + CTMuint mGridIndex; + + // Original index (before sorting). + CTMuint mOriginalIndex; +} _CTMsortvertex; + +//----------------------------------------------------------------------------- +// _ctmSetupGrid() - Setup the 3D space subdivision grid. +//----------------------------------------------------------------------------- +static void _ctmSetupGrid(_CTMcontext * self, _CTMgrid * aGrid) +{ + CTMuint i; + CTMfloat factor[3], sum, wantedGrids; + + // Calculate the mesh bounding box + aGrid->mMin[0] = aGrid->mMax[0] = self->mVertices[0]; + aGrid->mMin[1] = aGrid->mMax[1] = self->mVertices[1]; + aGrid->mMin[2] = aGrid->mMax[2] = self->mVertices[2]; + for(i = 1; i < self->mVertexCount; ++ i) + { + if(self->mVertices[i * 3] < aGrid->mMin[0]) + aGrid->mMin[0] = self->mVertices[i * 3]; + else if(self->mVertices[i * 3] > aGrid->mMax[0]) + aGrid->mMax[0] = self->mVertices[i * 3]; + if(self->mVertices[i * 3 + 1] < aGrid->mMin[1]) + aGrid->mMin[1] = self->mVertices[i * 3 + 1]; + else if(self->mVertices[i * 3 + 1] > aGrid->mMax[1]) + aGrid->mMax[1] = self->mVertices[i * 3 + 1]; + if(self->mVertices[i * 3 + 2] < aGrid->mMin[2]) + aGrid->mMin[2] = self->mVertices[i * 3 + 2]; + else if(self->mVertices[i * 3 + 2] > aGrid->mMax[2]) + aGrid->mMax[2] = self->mVertices[i * 3 + 2]; + } + + // Determine optimal grid resolution, based on the number of vertices and + // the bounding box. + // NOTE: This algorithm is quite crude, and could very well be optimized for + // better compression levels in the future without affecting the file format + // or backward compatibility at all. + for(i = 0; i < 3; ++ i) + factor[i] = aGrid->mMax[i] - aGrid->mMin[i]; + sum = factor[0] + factor[1] + factor[2]; + if(sum > 1e-30f) + { + sum = 1.0f / sum; + for(i = 0; i < 3; ++ i) + factor[i] *= sum; + wantedGrids = powf(100.0f * self->mVertexCount, 1.0f / 3.0f); + for(i = 0; i < 3; ++ i) + { + aGrid->mDivision[i] = (CTMuint) ceilf(wantedGrids * factor[i]); + if(aGrid->mDivision[i] < 1) + aGrid->mDivision[i] = 1; + } + } + else + { + aGrid->mDivision[0] = 4; + aGrid->mDivision[1] = 4; + aGrid->mDivision[2] = 4; + } +#ifdef __DEBUG_ + printf("Division: (%d %d %d)\n", aGrid->mDivision[0], aGrid->mDivision[1], aGrid->mDivision[2]); +#endif + + // Calculate grid sizes + for(i = 0; i < 3; ++ i) + aGrid->mSize[i] = (aGrid->mMax[i] - aGrid->mMin[i]) / aGrid->mDivision[i]; +} + +//----------------------------------------------------------------------------- +// _ctmPointToGridIdx() - Convert a point to a grid index. +//----------------------------------------------------------------------------- +static CTMuint _ctmPointToGridIdx(_CTMgrid * aGrid, CTMfloat * aPoint) +{ + CTMuint i, idx[3]; + + for(i = 0; i < 3; ++ i) + { + idx[i] = (CTMuint) floorf((aPoint[i] - aGrid->mMin[i]) / aGrid->mSize[i]); + if(idx[i] >= aGrid->mDivision[i]) + idx[i] = aGrid->mDivision[i] - 1; + } + + return idx[0] + aGrid->mDivision[0] * (idx[1] + aGrid->mDivision[1] * idx[2]); +} + +//----------------------------------------------------------------------------- +// _ctmGridIdxToPoint() - Convert a grid index to a point (the min x/y/z for +// the given grid box). +//----------------------------------------------------------------------------- +static void _ctmGridIdxToPoint(_CTMgrid * aGrid, CTMuint aIdx, CTMfloat * aPoint) +{ + CTMuint gridIdx[3], zdiv, ydiv, i; + + zdiv = aGrid->mDivision[0] * aGrid->mDivision[1]; + ydiv = aGrid->mDivision[0]; + + gridIdx[2] = aIdx / zdiv; + aIdx -= gridIdx[2] * zdiv; + gridIdx[1] = aIdx / ydiv; + aIdx -= gridIdx[1] * ydiv; + gridIdx[0] = aIdx; + + for(i = 0; i < 3; ++ i) + aPoint[i] = gridIdx[i] * aGrid->mSize[i] + aGrid->mMin[i]; +} + +//----------------------------------------------------------------------------- +// _compareVertex() - Comparator for the vertex sorting. +//----------------------------------------------------------------------------- +static int _compareVertex(const void * elem1, const void * elem2) +{ + _CTMsortvertex * v1 = (_CTMsortvertex *) elem1; + _CTMsortvertex * v2 = (_CTMsortvertex *) elem2; + if(v1->mGridIndex != v2->mGridIndex) + return v1->mGridIndex - v2->mGridIndex; + else if(v1->x < v2->x) + return -1; + else if(v1->x > v2->x) + return 1; + else + return 0; +} + +//----------------------------------------------------------------------------- +// _ctmSortVertices() - Setup the vertex array. Assign each vertex to a grid +// box, and sort all vertices. +//----------------------------------------------------------------------------- +static void _ctmSortVertices(_CTMcontext * self, _CTMsortvertex * aSortVertices, + _CTMgrid * aGrid) +{ + CTMuint i; + + // Prepare sort vertex array + for(i = 0; i < self->mVertexCount; ++ i) + { + // Store vertex properties in the sort vertex array + aSortVertices[i].x = self->mVertices[i * 3]; + aSortVertices[i].mGridIndex = _ctmPointToGridIdx(aGrid, &self->mVertices[i * 3]); + aSortVertices[i].mOriginalIndex = i; + } + + // Sort vertices. The elements are first sorted by their grid indices, and + // scondly by their x coordinates. + qsort((void *) aSortVertices, self->mVertexCount, sizeof(_CTMsortvertex), _compareVertex); +} + +//----------------------------------------------------------------------------- +// _ctmReIndexIndices() - Re-index all indices, based on the sorted vertices. +//----------------------------------------------------------------------------- +static int _ctmReIndexIndices(_CTMcontext * self, _CTMsortvertex * aSortVertices, + CTMuint * aIndices) +{ + CTMuint i, * indexLUT; + + // Create temporary lookup-array, O(n) + indexLUT = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); + if(!indexLUT) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + for(i = 0; i < self->mVertexCount; ++ i) + indexLUT[aSortVertices[i].mOriginalIndex] = i; + + // Convert old indices to new indices, O(n) + for(i = 0; i < self->mTriangleCount * 3; ++ i) + aIndices[i] = indexLUT[self->mIndices[i]]; + + // Free temporary lookup-array + free((void *) indexLUT); + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _compareTriangle() - Comparator for the triangle sorting. +//----------------------------------------------------------------------------- +static int _compareTriangle(const void * elem1, const void * elem2) +{ + CTMuint * tri1 = (CTMuint *) elem1; + CTMuint * tri2 = (CTMuint *) elem2; + if(tri1[0] != tri2[0]) + return tri1[0] - tri2[0]; + else + return tri1[1] - tri2[1]; +} + +//----------------------------------------------------------------------------- +// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal +// compression. +//----------------------------------------------------------------------------- +static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices) +{ + CTMuint * tri, tmp, i; + + // Step 1: Make sure that the first index of each triangle is the smallest + // one (rotate triangle nodes if necessary) + for(i = 0; i < self->mTriangleCount; ++ i) + { + tri = &aIndices[i * 3]; + if((tri[1] < tri[0]) && (tri[1] < tri[2])) + { + tmp = tri[0]; + tri[0] = tri[1]; + tri[1] = tri[2]; + tri[2] = tmp; + } + else if((tri[2] < tri[0]) && (tri[2] < tri[1])) + { + tmp = tri[0]; + tri[0] = tri[2]; + tri[2] = tri[1]; + tri[1] = tmp; + } + } + + // Step 2: Sort the triangles based on the first triangle index + qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle); +} + +//----------------------------------------------------------------------------- +// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to +// reduce data entropy. +//----------------------------------------------------------------------------- +static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices) +{ + CTMint i; + for(i = self->mTriangleCount - 1; i >= 0; -- i) + { + // Step 1: Calculate delta from second triangle index to the previous + // second triangle index, if the previous triangle shares the same first + // index, otherwise calculate the delta to the first triangle index + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) + aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1]; + else + aIndices[i * 3 + 1] -= aIndices[i * 3]; + + // Step 2: Calculate delta from third triangle index to the first triangle + // index + aIndices[i * 3 + 2] -= aIndices[i * 3]; + + // Step 3: Calculate derivative of the first triangle index + if(i >= 1) + aIndices[i * 3] -= aIndices[(i - 1) * 3]; + } +} + +//----------------------------------------------------------------------------- +// _ctmRestoreIndices() - Restore original indices (inverse derivative +// operation). +//----------------------------------------------------------------------------- +static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices) +{ + CTMuint i; + + for(i = 0; i < self->mTriangleCount; ++ i) + { + // Step 1: Reverse derivative of the first triangle index + if(i >= 1) + aIndices[i * 3] += aIndices[(i - 1) * 3]; + + // Step 2: Reverse delta from third triangle index to the first triangle + // index + aIndices[i * 3 + 2] += aIndices[i * 3]; + + // Step 3: Reverse delta from second triangle index to the previous + // second triangle index, if the previous triangle shares the same first + // index, otherwise reverse the delta to the first triangle index + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) + aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1]; + else + aIndices[i * 3 + 1] += aIndices[i * 3]; + } +} + +//----------------------------------------------------------------------------- +// _ctmMakeVertexDeltas() - Calculate various forms of derivatives in order to +// reduce data entropy. +//----------------------------------------------------------------------------- +static void _ctmMakeVertexDeltas(_CTMcontext * self, CTMint * aIntVertices, + _CTMsortvertex * aSortVertices, _CTMgrid * aGrid) +{ + CTMuint i, gridIdx, prevGridIndex, oldIdx; + CTMfloat gridOrigin[3], scale; + CTMint deltaX, prevDeltaX; + + // Vertex scaling factor + scale = 1.0f / self->mVertexPrecision; + + prevGridIndex = 0x7fffffff; + prevDeltaX = 0; + for(i = 0; i < self->mVertexCount; ++ i) + { + // Get grid box origin + gridIdx = aSortVertices[i].mGridIndex; + _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin); + + // Get old vertex coordinate index (before vertex sorting) + oldIdx = aSortVertices[i].mOriginalIndex; + + // Store delta to the grid box origin in the integer vertex array. For the + // X axis (which is sorted) we also do the delta to the previous coordinate + // in the box. + deltaX = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3] - gridOrigin[0]) + 0.5f); + if(gridIdx == prevGridIndex) + aIntVertices[i * 3] = deltaX - prevDeltaX; + else + aIntVertices[i * 3] = deltaX; + aIntVertices[i * 3 + 1] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 1] - gridOrigin[1]) + 0.5f); + aIntVertices[i * 3 + 2] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 2] - gridOrigin[2]) + 0.5f); + + prevGridIndex = gridIdx; + prevDeltaX = deltaX; + } +} + +//----------------------------------------------------------------------------- +// _ctmRestoreVertices() - Calculate inverse derivatives of the vertices. +//----------------------------------------------------------------------------- +static void _ctmRestoreVertices(_CTMcontext * self, CTMint * aIntVertices, + CTMuint * aGridIndices, _CTMgrid * aGrid, CTMfloat * aVertices) +{ + CTMuint i, gridIdx, prevGridIndex; + CTMfloat gridOrigin[3], scale; + CTMint deltaX, prevDeltaX; + + scale = self->mVertexPrecision; + + prevGridIndex = 0x7fffffff; + prevDeltaX = 0; + for(i = 0; i < self->mVertexCount; ++ i) + { + // Get grid box origin + gridIdx = aGridIndices[i]; + _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin); + + // Restore original point + deltaX = aIntVertices[i * 3]; + if(gridIdx == prevGridIndex) + deltaX += prevDeltaX; + aVertices[i * 3] = scale * deltaX + gridOrigin[0]; + aVertices[i * 3 + 1] = scale * aIntVertices[i * 3 + 1] + gridOrigin[1]; + aVertices[i * 3 + 2] = scale * aIntVertices[i * 3 + 2] + gridOrigin[2]; + + prevGridIndex = gridIdx; + prevDeltaX = deltaX; + } +} + +//----------------------------------------------------------------------------- +// _ctmCalcSmoothNormals() - Calculate the smooth normals for a given mesh. +// These are used as the nominal normals for normal deltas & reconstruction. +//----------------------------------------------------------------------------- +static void _ctmCalcSmoothNormals(_CTMcontext * self, CTMfloat * aVertices, + CTMuint * aIndices, CTMfloat * aSmoothNormals) +{ + CTMuint i, j, k, tri[3]; + CTMfloat len; + CTMfloat v1[3], v2[3], n[3]; + + // Clear smooth normals array + for(i = 0; i < 3 * self->mVertexCount; ++ i) + aSmoothNormals[i] = 0.0f; + + // Calculate sums of all neigbouring triangle normals for each vertex + for(i = 0; i < self->mTriangleCount; ++ i) + { + // Get triangle corner indices + for(j = 0; j < 3; ++ j) + tri[j] = aIndices[i * 3 + j]; + + // Calculate the normalized cross product of two triangle edges (i.e. the + // flat triangle normal) + for(j = 0; j < 3; ++ j) + { + v1[j] = aVertices[tri[1] * 3 + j] - aVertices[tri[0] * 3 + j]; + v2[j] = aVertices[tri[2] * 3 + j] - aVertices[tri[0] * 3 + j]; + } + n[0] = v1[1] * v2[2] - v1[2] * v2[1]; + n[1] = v1[2] * v2[0] - v1[0] * v2[2]; + n[2] = v1[0] * v2[1] - v1[1] * v2[0]; + len = sqrtf(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); + if(len > 1e-10f) + len = 1.0f / len; + else + len = 1.0f; + for(j = 0; j < 3; ++ j) + n[j] *= len; + + // Add the flat normal to all three triangle vertices + for(k = 0; k < 3; ++ k) + for(j = 0; j < 3; ++ j) + aSmoothNormals[tri[k] * 3 + j] += n[j]; + } + + // Normalize the normal sums, which gives the unit length smooth normals + for(i = 0; i < self->mVertexCount; ++ i) + { + len = sqrtf(aSmoothNormals[i * 3] * aSmoothNormals[i * 3] + + aSmoothNormals[i * 3 + 1] * aSmoothNormals[i * 3 + 1] + + aSmoothNormals[i * 3 + 2] * aSmoothNormals[i * 3 + 2]); + if(len > 1e-10f) + len = 1.0f / len; + else + len = 1.0f; + for(j = 0; j < 3; ++ j) + aSmoothNormals[i * 3 + j] *= len; + } +} + +//----------------------------------------------------------------------------- +// _ctmMakeNormalCoordSys() - Create an ortho-normalized coordinate system +// where the Z-axis is aligned with the given normal. +// Note 1: This function is central to how the compressed normal data is +// interpreted, and it can not be changed (mathematically) without making the +// coder/decoder incompatible with other versions of the library! +// Note 2: Since we do this for every single normal, this routine needs to be +// fast. The current implementation uses: 12 MUL, 1 DIV, 1 SQRT, ~6 ADD. +//----------------------------------------------------------------------------- +static void _ctmMakeNormalCoordSys(CTMfloat * aNormal, CTMfloat * aBasisAxes) +{ + CTMfloat len, * x, * y, * z; + CTMuint i; + + // Pointers to the basis axes (aBasisAxes is a 3x3 matrix) + x = aBasisAxes; + y = &aBasisAxes[3]; + z = &aBasisAxes[6]; + + // Z = normal (must be unit length!) + for(i = 0; i < 3; ++ i) + z[i] = aNormal[i]; + + // Calculate a vector that is guaranteed to be orthogonal to the normal, non- + // zero, and a continuous function of the normal (no discrete jumps): + // X = (0,0,1) x normal + (1,0,0) x normal + x[0] = -aNormal[1]; + x[1] = aNormal[0] - aNormal[2]; + x[2] = aNormal[1]; + + // Normalize the new X axis (note: |x[2]| = |x[0]|) + len = sqrtf(2.0 * x[0] * x[0] + x[1] * x[1]); + if(len > 1.0e-20f) + { + len = 1.0f / len; + x[0] *= len; + x[1] *= len; + x[2] *= len; + } + + // Let Y = Z x X (no normalization needed, since |Z| = |X| = 1) + y[0] = z[1] * x[2] - z[2] * x[1]; + y[1] = z[2] * x[0] - z[0] * x[2]; + y[2] = z[0] * x[1] - z[1] * x[0]; +} + +//----------------------------------------------------------------------------- +// _ctmMakeNormalDeltas() - Convert the normals to a new coordinate system: +// magnitude, phi, theta (relative to predicted smooth normals). +//----------------------------------------------------------------------------- +static CTMint _ctmMakeNormalDeltas(_CTMcontext * self, CTMint * aIntNormals, + CTMfloat * aVertices, CTMuint * aIndices, _CTMsortvertex * aSortVertices) +{ + CTMuint i, j, oldIdx, intPhi; + CTMfloat magn, phi, theta, scale, thetaScale; + CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9]; + + // Allocate temporary memory for the nominal vertex normals + smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount); + if(!smoothNormals) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Calculate smooth normals (Note: aVertices and aIndices use the sorted + // index space, so smoothNormals will too) + _ctmCalcSmoothNormals(self, aVertices, aIndices, smoothNormals); + + // Normal scaling factor + scale = 1.0f / self->mNormalPrecision; + + for(i = 0; i < self->mVertexCount; ++ i) + { + // Get old normal index (before vertex sorting) + oldIdx = aSortVertices[i].mOriginalIndex; + + // Calculate normal magnitude (should always be 1.0 for unit length normals) + magn = sqrtf(self->mNormals[oldIdx * 3] * self->mNormals[oldIdx * 3] + + self->mNormals[oldIdx * 3 + 1] * self->mNormals[oldIdx * 3 + 1] + + self->mNormals[oldIdx * 3 + 2] * self->mNormals[oldIdx * 3 + 2]); + if(magn < 1e-10f) + magn = 1.0f; + + // Invert magnitude if the normal is negative compared to the predicted + // smooth normal + if((smoothNormals[i * 3] * self->mNormals[oldIdx * 3] + + smoothNormals[i * 3 + 1] * self->mNormals[oldIdx * 3 + 1] + + smoothNormals[i * 3 + 2] * self->mNormals[oldIdx * 3 + 2]) < 0.0f) + magn = -magn; + + // Store the magnitude in the first element of the three normal elements + aIntNormals[i * 3] = (CTMint) floorf(scale * magn + 0.5f); + + // Normalize the normal (1 / magn) - and flip it if magn < 0 + magn = 1.0f / magn; + for(j = 0; j < 3; ++ j) + n[j] = self->mNormals[oldIdx * 3 + j] * magn; + + // Convert the normal to angular representation (phi, theta) in a coordinate + // system where the nominal (smooth) normal is the Z-axis + _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes); + for(j = 0; j < 3; ++ j) + n2[j] = basisAxes[j * 3] * n[0] + + basisAxes[j * 3 + 1] * n[1] + + basisAxes[j * 3 + 2] * n[2]; + if(n2[2] >= 1.0f) + phi = 0.0f; + else + phi = acosf(n2[2]); + theta = atan2f(n2[1], n2[0]); + + // Round phi and theta (spherical coordinates) to integers. Note: We let the + // theta resolution vary with the x/y circumference (roughly phi). + intPhi = (CTMint) floorf(phi * (scale / (0.5f * PI)) + 0.5f); + if(intPhi == 0) + thetaScale = 0.0f; + else if(intPhi <= 4) + thetaScale = 2.0f / PI; + else + thetaScale = ((CTMfloat) intPhi) / (2.0f * PI); + aIntNormals[i * 3 + 1] = intPhi; + aIntNormals[i * 3 + 2] = (CTMint) floorf((theta + PI) * thetaScale + 0.5f); + } + + // Free temporary resources + free(smoothNormals); + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _ctmRestoreNormals() - Convert the normals back to cartesian coordinates. +//----------------------------------------------------------------------------- +static CTMint _ctmRestoreNormals(_CTMcontext * self, CTMint * aIntNormals) +{ + CTMuint i, j, intPhi; + CTMfloat magn, phi, theta, scale, thetaScale; + CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9]; + + // Allocate temporary memory for the nominal vertex normals + smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount); + if(!smoothNormals) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Calculate smooth normals (nominal normals) + _ctmCalcSmoothNormals(self, self->mVertices, self->mIndices, smoothNormals); + + // Normal scaling factor + scale = self->mNormalPrecision; + + for(i = 0; i < self->mVertexCount; ++ i) + { + // Get the normal magnitude from the first of the three normal elements + magn = aIntNormals[i * 3] * scale; + + // Get phi and theta (spherical coordinates, relative to the smooth normal). + intPhi = aIntNormals[i * 3 + 1]; + phi = intPhi * (0.5f * PI) * scale; + if(intPhi == 0) + thetaScale = 0.0f; + else if(intPhi <= 4) + thetaScale = PI / 2.0f; + else + thetaScale = (2.0f * PI) / ((CTMfloat) intPhi); + theta = aIntNormals[i * 3 + 2] * thetaScale - PI; + + // Convert the normal from the angular representation (phi, theta) back to + // cartesian coordinates + n2[0] = sinf(phi) * cosf(theta); + n2[1] = sinf(phi) * sinf(theta); + n2[2] = cosf(phi); + _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes); + for(j = 0; j < 3; ++ j) + n[j] = basisAxes[j] * n2[0] + + basisAxes[3 + j] * n2[1] + + basisAxes[6 + j] * n2[2]; + + // Apply normal magnitude, and output to the normals array + for(j = 0; j < 3; ++ j) + self->mNormals[i * 3 + j] = n[j] * magn; + } + + // Free temporary resources + free(smoothNormals); + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _ctmMakeUVCoordDeltas() - Calculate various forms of derivatives in order +// to reduce data entropy. +//----------------------------------------------------------------------------- +static void _ctmMakeUVCoordDeltas(_CTMcontext * self, _CTMfloatmap * aMap, + CTMint * aIntUVCoords, _CTMsortvertex * aSortVertices) +{ + CTMuint i, oldIdx; + CTMint u, v, prevU, prevV; + CTMfloat scale; + + // UV coordinate scaling factor + scale = 1.0f / aMap->mPrecision; + + prevU = prevV = 0; + for(i = 0; i < self->mVertexCount; ++ i) + { + // Get old UV coordinate index (before vertex sorting) + oldIdx = aSortVertices[i].mOriginalIndex; + + // Convert to fixed point + u = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2] + 0.5f); + v = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2 + 1] + 0.5f); + + // Calculate delta and store it in the converted array. NOTE: Here we rely + // on the fact that vertices are sorted, and usually close to each other, + // which means that UV coordinates should also be close to each other... + aIntUVCoords[i * 2] = u - prevU; + aIntUVCoords[i * 2 + 1] = v - prevV; + + prevU = u; + prevV = v; + } +} + +//----------------------------------------------------------------------------- +// _ctmRestoreUVCoords() - Calculate inverse derivatives of the UV +// coordinates. +//----------------------------------------------------------------------------- +static void _ctmRestoreUVCoords(_CTMcontext * self, _CTMfloatmap * aMap, + CTMint * aIntUVCoords) +{ + CTMuint i; + CTMint u, v, prevU, prevV; + CTMfloat scale; + + // UV coordinate scaling factor + scale = aMap->mPrecision; + + prevU = prevV = 0; + for(i = 0; i < self->mVertexCount; ++ i) + { + // Calculate inverse delta + u = aIntUVCoords[i * 2] + prevU; + v = aIntUVCoords[i * 2 + 1] + prevV; + + // Convert to floating point + aMap->mValues[i * 2] = (CTMfloat) u * scale; + aMap->mValues[i * 2 + 1] = (CTMfloat) v * scale; + + prevU = u; + prevV = v; + } +} + +//----------------------------------------------------------------------------- +// _ctmMakeAttribDeltas() - Calculate various forms of derivatives in order +// to reduce data entropy. +//----------------------------------------------------------------------------- +static void _ctmMakeAttribDeltas(_CTMcontext * self, _CTMfloatmap * aMap, + CTMint * aIntAttribs, _CTMsortvertex * aSortVertices) +{ + CTMuint i, j, oldIdx; + CTMint value[4], prev[4]; + CTMfloat scale; + + // Attribute scaling factor + scale = 1.0f / aMap->mPrecision; + + for(j = 0; j < 4; ++ j) + prev[j] = 0; + + for(i = 0; i < self->mVertexCount; ++ i) + { + // Get old attribute index (before vertex sorting) + oldIdx = aSortVertices[i].mOriginalIndex; + + // Convert to fixed point, and calculate delta and store it in the converted + // array. NOTE: Here we rely on the fact that vertices are sorted, and + // usually close to each other, which means that attributes should also + // be close to each other (and we assume that they somehow vary slowly with + // the geometry)... + for(j = 0; j < 4; ++ j) + { + value[j] = (CTMint) floorf(scale * aMap->mValues[oldIdx * 4 + j] + 0.5f); + aIntAttribs[i * 4 + j] = value[j] - prev[j]; + prev[j] = value[j]; + } + } +} + +//----------------------------------------------------------------------------- +// _ctmRestoreAttribs() - Calculate inverse derivatives of the vertex +// attributes. +//----------------------------------------------------------------------------- +static void _ctmRestoreAttribs(_CTMcontext * self, _CTMfloatmap * aMap, + CTMint * aIntAttribs) +{ + CTMuint i, j; + CTMint value[4], prev[4]; + CTMfloat scale; + + // Attribute scaling factor + scale = aMap->mPrecision; + + for(j = 0; j < 4; ++ j) + prev[j] = 0; + + for(i = 0; i < self->mVertexCount; ++ i) + { + // Calculate inverse delta, and convert to floating point + for(j = 0; j < 4; ++ j) + { + value[j] = aIntAttribs[i * 4 + j] + prev[j]; + aMap->mValues[i * 4 + j] = (CTMfloat) value[j] * scale; + prev[j] = value[j]; + } + } +} + +//----------------------------------------------------------------------------- +// _ctmCompressMesh_MG2() - Compress the mesh that is stored in the CTM +// context, and write it the the output stream in the CTM context. +//----------------------------------------------------------------------------- +int _ctmCompressMesh_MG2(_CTMcontext * self) +{ + _CTMgrid grid; + _CTMsortvertex * sortVertices; + _CTMfloatmap * map; + CTMuint * indices, * deltaIndices, * gridIndices; + CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs; + CTMfloat * restoredVertices; + CTMuint i; + +#ifdef __DEBUG_ + printf("COMPRESSION METHOD: MG2\n"); +#endif + + // Setup 3D space subdivision grid + _ctmSetupGrid(self, &grid); + + // Write MG2-specific header information to the stream + _ctmStreamWrite(self, (void *) "MG2H", 4); + _ctmStreamWriteFLOAT(self, self->mVertexPrecision); + _ctmStreamWriteFLOAT(self, self->mNormalPrecision); + _ctmStreamWriteFLOAT(self, grid.mMin[0]); + _ctmStreamWriteFLOAT(self, grid.mMin[1]); + _ctmStreamWriteFLOAT(self, grid.mMin[2]); + _ctmStreamWriteFLOAT(self, grid.mMax[0]); + _ctmStreamWriteFLOAT(self, grid.mMax[1]); + _ctmStreamWriteFLOAT(self, grid.mMax[2]); + _ctmStreamWriteUINT(self, grid.mDivision[0]); + _ctmStreamWriteUINT(self, grid.mDivision[1]); + _ctmStreamWriteUINT(self, grid.mDivision[2]); + + // Prepare (sort) vertices + sortVertices = (_CTMsortvertex *) malloc(sizeof(_CTMsortvertex) * self->mVertexCount); + if(!sortVertices) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + _ctmSortVertices(self, sortVertices, &grid); + + // Convert vertices to integers and calculate vertex deltas (entropy-reduction) + intVertices = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount); + if(!intVertices) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) sortVertices); + return CTM_FALSE; + } + _ctmMakeVertexDeltas(self, intVertices, sortVertices, &grid); + + // Write vertices +#ifdef __DEBUG_ + printf("Vertices: "); +#endif + _ctmStreamWrite(self, (void *) "VERT", 4); + if(!_ctmStreamWritePackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE)) + { + free((void *) intVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + + // Prepare grid indices (deltas) + gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); + if(!gridIndices) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) intVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + gridIndices[0] = sortVertices[0].mGridIndex; + for(i = 1; i < self->mVertexCount; ++ i) + gridIndices[i] = sortVertices[i].mGridIndex - sortVertices[i - 1].mGridIndex; + + // Write grid indices +#ifdef __DEBUG_ + printf("Grid indices: "); +#endif + _ctmStreamWrite(self, (void *) "GIDX", 4); + if(!_ctmStreamWritePackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE)) + { + free((void *) gridIndices); + free((void *) intVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + + // Calculate the result of the compressed -> decompressed vertices, in order + // to use the same vertex data for calculating nominal normals as the + // decompression routine (i.e. compensate for the vertex error when + // calculating the normals) + restoredVertices = (CTMfloat *) malloc(sizeof(CTMfloat) * 3 * self->mVertexCount); + if(!restoredVertices) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) gridIndices); + free((void *) intVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + for(i = 1; i < self->mVertexCount; ++ i) + gridIndices[i] += gridIndices[i - 1]; + _ctmRestoreVertices(self, intVertices, gridIndices, &grid, restoredVertices); + + // Free temporary resources + free((void *) gridIndices); + free((void *) intVertices); + + // Perpare (sort) indices + indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); + if(!indices) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) restoredVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + if(!_ctmReIndexIndices(self, sortVertices, indices)) + { + free((void *) indices); + free((void *) restoredVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + _ctmReArrangeTriangles(self, indices); + + // Calculate index deltas (entropy-reduction) + deltaIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); + if(!indices) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) indices); + free((void *) restoredVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + for(i = 0; i < self->mTriangleCount * 3; ++ i) + deltaIndices[i] = indices[i]; + _ctmMakeIndexDeltas(self, deltaIndices); + + // Write triangle indices +#ifdef __DEBUG_ + printf("Indices: "); +#endif + _ctmStreamWrite(self, (void *) "INDX", 4); + if(!_ctmStreamWritePackedInts(self, (CTMint *) deltaIndices, self->mTriangleCount, 3, CTM_FALSE)) + { + free((void *) deltaIndices); + free((void *) indices); + free((void *) restoredVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + + // Free temporary data for the indices + free((void *) deltaIndices); + + if(self->mNormals) + { + // Convert normals to integers and calculate deltas (entropy-reduction) + intNormals = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount); + if(!intNormals) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) indices); + free((void *) restoredVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + if(!_ctmMakeNormalDeltas(self, intNormals, restoredVertices, indices, sortVertices)) + { + free((void *) indices); + free((void *) intNormals); + free((void *) restoredVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + + // Write normals +#ifdef __DEBUG_ + printf("Normals: "); +#endif + _ctmStreamWrite(self, (void *) "NORM", 4); + if(!_ctmStreamWritePackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE)) + { + free((void *) indices); + free((void *) intNormals); + free((void *) restoredVertices); + free((void *) sortVertices); + return CTM_FALSE; + } + + // Free temporary normal data + free((void *) intNormals); + } + + // Free restored indices and vertices + free((void *) indices); + free((void *) restoredVertices); + + // Write UV maps + map = self->mUVMaps; + while(map) + { + // Convert UV coordinates to integers and calculate deltas (entropy-reduction) + intUVCoords = (CTMint *) malloc(sizeof(CTMint) * 2 * self->mVertexCount); + if(!intUVCoords) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) sortVertices); + return CTM_FALSE; + } + _ctmMakeUVCoordDeltas(self, map, intUVCoords, sortVertices); + + // Write UV coordinates +#ifdef __DEBUG_ + printf("Texture coordinates (%s): ", map->mName ? map->mName : "no name"); +#endif + _ctmStreamWrite(self, (void *) "TEXC", 4); + _ctmStreamWriteSTRING(self, map->mName); + _ctmStreamWriteSTRING(self, map->mFileName); + _ctmStreamWriteFLOAT(self, map->mPrecision); + if(!_ctmStreamWritePackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE)) + { + free((void *) intUVCoords); + free((void *) sortVertices); + return CTM_FALSE; + } + + // Free temporary UV coordinate data + free((void *) intUVCoords); + + map = map->mNext; + } + + // Write vertex attribute maps + map = self->mAttribMaps; + while(map) + { + // Convert vertex attributes to integers and calculate deltas (entropy-reduction) + intAttribs = (CTMint *) malloc(sizeof(CTMint) * 4 * self->mVertexCount); + if(!intAttribs) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) sortVertices); + return CTM_FALSE; + } + _ctmMakeAttribDeltas(self, map, intAttribs, sortVertices); + + // Write vertex attributes +#ifdef __DEBUG_ + printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name"); +#endif + _ctmStreamWrite(self, (void *) "ATTR", 4); + _ctmStreamWriteSTRING(self, map->mName); + _ctmStreamWriteFLOAT(self, map->mPrecision); + if(!_ctmStreamWritePackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE)) + { + free((void *) intAttribs); + free((void *) sortVertices); + return CTM_FALSE; + } + + // Free temporary vertex attribute data + free((void *) intAttribs); + + map = map->mNext; + } + + // Free temporary data + free((void *) sortVertices); + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _ctmUncompressMesh_MG2() - Uncmpress the mesh from the input stream in the +// CTM context, and store the resulting mesh in the CTM context. +//----------------------------------------------------------------------------- +int _ctmUncompressMesh_MG2(_CTMcontext * self) +{ + CTMuint * gridIndices, i; + CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs; + _CTMfloatmap * map; + _CTMgrid grid; + + // Read MG2-specific header information from the stream + if(_ctmStreamReadUINT(self) != FOURCC("MG2H")) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + self->mVertexPrecision = _ctmStreamReadFLOAT(self); + if(self->mVertexPrecision <= 0.0f) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + self->mNormalPrecision = _ctmStreamReadFLOAT(self); + if(self->mNormalPrecision <= 0.0f) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + grid.mMin[0] = _ctmStreamReadFLOAT(self); + grid.mMin[1] = _ctmStreamReadFLOAT(self); + grid.mMin[2] = _ctmStreamReadFLOAT(self); + grid.mMax[0] = _ctmStreamReadFLOAT(self); + grid.mMax[1] = _ctmStreamReadFLOAT(self); + grid.mMax[2] = _ctmStreamReadFLOAT(self); + if((grid.mMax[0] < grid.mMin[0]) || + (grid.mMax[1] < grid.mMin[1]) || + (grid.mMax[2] < grid.mMin[2])) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + grid.mDivision[0] = _ctmStreamReadUINT(self); + grid.mDivision[1] = _ctmStreamReadUINT(self); + grid.mDivision[2] = _ctmStreamReadUINT(self); + if((grid.mDivision[0] < 1) || (grid.mDivision[1] < 1) || (grid.mDivision[2] < 1)) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + + // Initialize 3D space subdivision grid + for(i = 0; i < 3; ++ i) + grid.mSize[i] = (grid.mMax[i] - grid.mMin[i]) / grid.mDivision[i]; + + // Read vertices + if(_ctmStreamReadUINT(self) != FOURCC("VERT")) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + intVertices = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3); + if(!intVertices) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + if(!_ctmStreamReadPackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE)) + { + free((void *) intVertices); + return CTM_FALSE; + } + + // Read grid indices + if(_ctmStreamReadUINT(self) != FOURCC("GIDX")) + { + free((void *) intVertices); + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); + if(!gridIndices) + { + self->mError = CTM_OUT_OF_MEMORY; + free((void *) intVertices); + return CTM_FALSE; + } + if(!_ctmStreamReadPackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE)) + { + free((void *) gridIndices); + free((void *) intVertices); + return CTM_FALSE; + } + + // Restore grid indices (deltas) + for(i = 1; i < self->mVertexCount; ++ i) + gridIndices[i] += gridIndices[i - 1]; + + // Restore vertices + _ctmRestoreVertices(self, intVertices, gridIndices, &grid, self->mVertices); + + // Free temporary resources + free((void *) gridIndices); + free((void *) intVertices); + + // Read triangle indices + if(_ctmStreamReadUINT(self) != FOURCC("INDX")) + { + self->mError = CTM_BAD_FORMAT; + return CTM_FALSE; + } + if(!_ctmStreamReadPackedInts(self, (CTMint *) self->mIndices, self->mTriangleCount, 3, CTM_FALSE)) + return CTM_FALSE; + + // Restore indices + _ctmRestoreIndices(self, self->mIndices); + + // Check that all indices are within range + for(i = 0; i < (self->mTriangleCount * 3); ++ i) + { + if(self->mIndices[i] >= self->mVertexCount) + { + self->mError = CTM_INVALID_MESH; + return CTM_FALSE; + } + } + + // Read normals + if(self->mNormals) + { + intNormals = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3); + if(!intNormals) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + if(_ctmStreamReadUINT(self) != FOURCC("NORM")) + { + self->mError = CTM_BAD_FORMAT; + free((void *) intNormals); + return CTM_FALSE; + } + if(!_ctmStreamReadPackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE)) + { + free((void *) intNormals); + return CTM_FALSE; + } + + // Restore normals + if(!_ctmRestoreNormals(self, intNormals)) + { + free((void *) intNormals); + return CTM_FALSE; + } + + // Free temporary normals data + free((void *) intNormals); + } + + // Read UV maps + map = self->mUVMaps; + while(map) + { + intUVCoords = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 2); + if(!intUVCoords) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) + { + self->mError = CTM_BAD_FORMAT; + free((void *) intUVCoords); + return CTM_FALSE; + } + _ctmStreamReadSTRING(self, &map->mName); + _ctmStreamReadSTRING(self, &map->mFileName); + map->mPrecision = _ctmStreamReadFLOAT(self); + if(map->mPrecision <= 0.0f) + { + self->mError = CTM_BAD_FORMAT; + free((void *) intUVCoords); + return CTM_FALSE; + } + if(!_ctmStreamReadPackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE)) + { + free((void *) intUVCoords); + return CTM_FALSE; + } + + // Restore UV coordinates + _ctmRestoreUVCoords(self, map, intUVCoords); + + // Free temporary UV coordinate data + free((void *) intUVCoords); + + map = map->mNext; + } + + // Read vertex attribute maps + map = self->mAttribMaps; + while(map) + { + intAttribs = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 4); + if(!intAttribs) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) + { + self->mError = CTM_BAD_FORMAT; + free((void *) intAttribs); + return CTM_FALSE; + } + _ctmStreamReadSTRING(self, &map->mName); + map->mPrecision = _ctmStreamReadFLOAT(self); + if(map->mPrecision <= 0.0f) + { + self->mError = CTM_BAD_FORMAT; + free((void *) intAttribs); + return CTM_FALSE; + } + if(!_ctmStreamReadPackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE)) + { + free((void *) intAttribs); + return CTM_FALSE; + } + + // Restore vertex attributes + _ctmRestoreAttribs(self, map, intAttribs); + + // Free temporary vertex attribute data + free((void *) intAttribs); + + map = map->mNext; + } + + return CTM_TRUE; +} diff --git a/src/external/OpenCTM-1.0.3/lib/compressRAW.c b/src/external/OpenCTM-1.0.3/lib/compressRAW.c new file mode 100644 index 000000000..b3c781102 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/compressRAW.c @@ -0,0 +1,181 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: compressRAW.c +// Description: Implementation of the RAW compression method. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +#include "openctm.h" +#include "internal.h" + +#ifdef __DEBUG_ +#include +#endif + + +//----------------------------------------------------------------------------- +// _ctmCompressMesh_RAW() - Compress the mesh that is stored in the CTM +// context using the RAW method, and write it the the output stream in the CTM +// context. +//----------------------------------------------------------------------------- +int _ctmCompressMesh_RAW(_CTMcontext * self) +{ + CTMuint i; + _CTMfloatmap * map; + +#ifdef __DEBUG_ + printf("COMPRESSION METHOD: RAW\n"); +#endif + + // Write triangle indices +#ifdef __DEBUG_ + printf("Inidices: %d bytes\n", (CTMuint)(self->mTriangleCount * 3 * sizeof(CTMuint))); +#endif + _ctmStreamWrite(self, (void *) "INDX", 4); + for(i = 0; i < self->mTriangleCount * 3; ++ i) + _ctmStreamWriteUINT(self, self->mIndices[i]); + + // Write vertices +#ifdef __DEBUG_ + printf("Vertices: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat))); +#endif + _ctmStreamWrite(self, (void *) "VERT", 4); + for(i = 0; i < self->mVertexCount * 3; ++ i) + _ctmStreamWriteFLOAT(self, self->mVertices[i]); + + // Write normals + if(self->mNormals) + { +#ifdef __DEBUG_ + printf("Normals: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat))); +#endif + _ctmStreamWrite(self, (void *) "NORM", 4); + for(i = 0; i < self->mVertexCount * 3; ++ i) + _ctmStreamWriteFLOAT(self, self->mNormals[i]); + } + + // Write UV maps + map = self->mUVMaps; + while(map) + { +#ifdef __DEBUG_ + printf("UV coordinates (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 2 * sizeof(CTMfloat))); +#endif + _ctmStreamWrite(self, (void *) "TEXC", 4); + _ctmStreamWriteSTRING(self, map->mName); + _ctmStreamWriteSTRING(self, map->mFileName); + for(i = 0; i < self->mVertexCount * 2; ++ i) + _ctmStreamWriteFLOAT(self, map->mValues[i]); + map = map->mNext; + } + + // Write attribute maps + map = self->mAttribMaps; + while(map) + { +#ifdef __DEBUG_ + printf("Vertex attributes (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 4 * sizeof(CTMfloat))); +#endif + _ctmStreamWrite(self, (void *) "ATTR", 4); + _ctmStreamWriteSTRING(self, map->mName); + for(i = 0; i < self->mVertexCount * 4; ++ i) + _ctmStreamWriteFLOAT(self, map->mValues[i]); + map = map->mNext; + } + + return 1; +} + +//----------------------------------------------------------------------------- +// _ctmUncompressMesh_RAW() - Uncmpress the mesh from the input stream in the +// CTM context using the RAW method, and store the resulting mesh in the CTM +// context. +//----------------------------------------------------------------------------- +int _ctmUncompressMesh_RAW(_CTMcontext * self) +{ + CTMuint i; + _CTMfloatmap * map; + + // Read triangle indices + if(_ctmStreamReadUINT(self) != FOURCC("INDX")) + { + self->mError = CTM_BAD_FORMAT; + return 0; + } + for(i = 0; i < self->mTriangleCount * 3; ++ i) + self->mIndices[i] = _ctmStreamReadUINT(self); + + // Read vertices + if(_ctmStreamReadUINT(self) != FOURCC("VERT")) + { + self->mError = CTM_BAD_FORMAT; + return 0; + } + for(i = 0; i < self->mVertexCount * 3; ++ i) + self->mVertices[i] = _ctmStreamReadFLOAT(self); + + // Read normals + if(self->mNormals) + { + if(_ctmStreamReadUINT(self) != FOURCC("NORM")) + { + self->mError = CTM_BAD_FORMAT; + return 0; + } + for(i = 0; i < self->mVertexCount * 3; ++ i) + self->mNormals[i] = _ctmStreamReadFLOAT(self); + } + + // Read UV maps + map = self->mUVMaps; + while(map) + { + if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) + { + self->mError = CTM_BAD_FORMAT; + return 0; + } + _ctmStreamReadSTRING(self, &map->mName); + _ctmStreamReadSTRING(self, &map->mFileName); + for(i = 0; i < self->mVertexCount * 2; ++ i) + map->mValues[i] = _ctmStreamReadFLOAT(self); + map = map->mNext; + } + + // Read attribute maps + map = self->mAttribMaps; + while(map) + { + if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) + { + self->mError = CTM_BAD_FORMAT; + return 0; + } + _ctmStreamReadSTRING(self, &map->mName); + for(i = 0; i < self->mVertexCount * 4; ++ i) + map->mValues[i] = _ctmStreamReadFLOAT(self); + map = map->mNext; + } + + return 1; +} diff --git a/src/external/OpenCTM-1.0.3/lib/internal.h b/src/external/OpenCTM-1.0.3/lib/internal.h new file mode 100644 index 000000000..2e65c86ba --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/internal.h @@ -0,0 +1,147 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: internal.h +// Description: Internal (private) declarations, types and function prototypes. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +#ifndef __OPENCTM_INTERNAL_H_ +#define __OPENCTM_INTERNAL_H_ + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- +// OpenCTM file format version (v5). +#define _CTM_FORMAT_VERSION 0x00000005 + +// Flags for the Mesh flags field of the file header +#define _CTM_HAS_NORMALS_BIT 0x00000001 + +//----------------------------------------------------------------------------- +// _CTMfloatmap - Internal representation of a floating point based vertex map +// (used for UV maps and attribute maps). +//----------------------------------------------------------------------------- +typedef struct _CTMfloatmap_struct _CTMfloatmap; +struct _CTMfloatmap_struct { + char * mName; // Unique name + char * mFileName; // File name reference (used only for UV maps) + CTMfloat mPrecision; // Precision for this map + CTMfloat * mValues; // Attribute/UV coordinate values (per vertex) + _CTMfloatmap * mNext; // Pointer to the next map in the list (linked list) +}; + +//----------------------------------------------------------------------------- +// _CTMcontext - Internal CTM context structure. +//----------------------------------------------------------------------------- +typedef struct { + // Context mode (import or export) + CTMenum mMode; + + // Vertices + CTMfloat * mVertices; + CTMuint mVertexCount; + + // Indices + CTMuint * mIndices; + CTMuint mTriangleCount; + + // Normals (optional) + CTMfloat * mNormals; + + // Multiple sets of UV coordinate maps (optional) + CTMuint mUVMapCount; + _CTMfloatmap * mUVMaps; + + // Multiple sets of custom vertex attribute maps (optional) + CTMuint mAttribMapCount; + _CTMfloatmap * mAttribMaps; + + // Last error code + CTMenum mError; + + // The selected compression method + CTMenum mMethod; + + // The selected compression level + CTMuint mCompressionLevel; + + // Vertex coordinate precision + CTMfloat mVertexPrecision; + + // Normal precision (angular + magnitude) + CTMfloat mNormalPrecision; + + // File comment + char * mFileComment; + + // Read() function pointer + CTMreadfn mReadFn; + + // Write() function pointer + CTMwritefn mWriteFn; + + // User data (for stream read/write - usually the stream handle) + void * mUserData; +} _CTMcontext; + +//----------------------------------------------------------------------------- +// Macros +//----------------------------------------------------------------------------- +#define FOURCC(str) (((CTMuint) str[0]) | (((CTMuint) str[1]) << 8) | \ + (((CTMuint) str[2]) << 16) | (((CTMuint) str[3]) << 24)) + +//----------------------------------------------------------------------------- +// Funcion prototypes for stream.c +//----------------------------------------------------------------------------- +CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount); +CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount); +CTMuint _ctmStreamReadUINT(_CTMcontext * self); +void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue); +CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self); +void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue); +void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue); +void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue); +int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts); +int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts); +int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize); +int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize); + +//----------------------------------------------------------------------------- +// Funcion prototypes for compressRAW.c +//----------------------------------------------------------------------------- +int _ctmCompressMesh_RAW(_CTMcontext * self); +int _ctmUncompressMesh_RAW(_CTMcontext * self); + +//----------------------------------------------------------------------------- +// Funcion prototypes for compressMG1.c +//----------------------------------------------------------------------------- +int _ctmCompressMesh_MG1(_CTMcontext * self); +int _ctmUncompressMesh_MG1(_CTMcontext * self); + +//----------------------------------------------------------------------------- +// Funcion prototypes for compressMG2.c +//----------------------------------------------------------------------------- +int _ctmCompressMesh_MG2(_CTMcontext * self); +int _ctmUncompressMesh_MG2(_CTMcontext * self); + +#endif // __OPENCTM_INTERNAL_H_ diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.c b/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.c new file mode 100644 index 000000000..358a7b526 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.c @@ -0,0 +1,127 @@ +/* Alloc.c -- Memory allocation functions +2008-09-24 +Igor Pavlov +Public domain */ + +#ifdef _WIN32 +#include +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); + #endif + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifndef MEM_LARGE_PAGES +#undef _7ZIP_LARGE_PAGES +#endif + +#ifdef _7ZIP_LARGE_PAGES +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); +#endif + +void SetLargePageSize() +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size = 0; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) + { + void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.h b/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.h new file mode 100644 index 000000000..510d18e4d --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/Alloc.h @@ -0,0 +1,34 @@ +/* Alloc.h -- Memory allocation functions +2008-03-13 +Igor Pavlov +Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include + +#include "NameMangle.h" + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.c new file mode 100644 index 000000000..34f4f09ea --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.c @@ -0,0 +1,751 @@ +/* LzFind.c -- Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#include + +#include "LzFind.h" +#include "LzHash.h" + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +#define kNormalizeMask (~(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)3 << 30) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + if (!p->directInput) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (p->bufferBase == 0 || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != 0); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } + +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + p->result = p->stream->Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + /* p->skipModeBits = 0; */ + p->directInput = 0; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + UInt32 i; + p->bufferBase = 0; + p->directInput = 0; + p->hash = 0; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hash); + p->hash = 0; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return 0; + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc) +{ + UInt32 sizeReserv; + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + sizeReserv = historySize >> 1; + if (historySize > ((UInt32)2 << 30)) + sizeReserv = historySize >> 2; + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + /* hs >>= p->skipModeBits; */ + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + UInt32 prevSize = p->hashSizeSum + p->numSons; + UInt32 newSize; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); + newSize = p->hashSizeSum + p->numSons; + if (p->hash != 0 && prevSize == newSize) + return 1; + MatchFinder_FreeThisClassMemory(p, alloc); + p->hash = AllocRefs(newSize, alloc); + if (p->hash != 0) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + if (limit2 < limit) + limit = limit2; + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + +void MatchFinder_Init(CMatchFinder *p) +{ + UInt32 i; + for (i = 0; i < p->hashSizeSum; i++) + p->hash[i] = kEmptyHashValue; + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + MatchFinder_ReadBlock(p); + MatchFinder_SetLimits(p); +} + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +{ + UInt32 i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); + MatchFinder_ReduceOffsets(p, subValue); +} + +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } +} + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, delta2, maxLen, offset; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + delta2 = p->pos - p->hash[hash2Value]; + curMatch = p->hash[kFix3HashSize + hashValue]; + + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + + + maxLen = 2; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[0] = maxLen; + distances[1] = delta2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value; + SKIP_HEADER(3) + HASH3_CALC; + curMatch = p->hash[kFix3HashSize + hashValue]; + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = p->pos; + p->hash[kFix4HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.h new file mode 100644 index 000000000..5b9cebfdf --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzFind.h @@ -0,0 +1,107 @@ +/* LzFind.h -- Match finder for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZFIND_H +#define __LZFIND_H + +#include "Types.h" + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + int streamEndWasReached; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + int directInput; + int btMode; + /* int skipModeBits; */ + int bigHash; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + UInt32 numSons; + SRes result; + UInt32 crc[256]; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +int MatchFinder_NeedMove(CMatchFinder *p); +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetIndexByte_Func GetIndexByte; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +void MatchFinder_Init(CMatchFinder *p); +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzHash.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzHash.h new file mode 100644 index 000000000..9f4173e7e --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzHash.h @@ -0,0 +1,54 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZHASH_H +#define __LZHASH_H + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +#define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ + hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ + hash4Value &= (kHash4Size - 1); } + +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.c new file mode 100644 index 000000000..d87eb1914 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.c @@ -0,0 +1,1007 @@ +/* LzmaDec.c -- LZMA Decoder +2008-11-06 : Igor Pavlov : Public domain */ + +#include "LzmaDec.h" + +#include + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +static const Byte kLiteralNextStates[kNumStates * 2] = +{ + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, + 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 +}; + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + symbol = 1; + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + + state = kLiteralNextStates[state]; + /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + /* state = kLiteralNextStates[state]; */ + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len-- != 0) + { + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT inSize = *srcLen; + SizeT outSize = *destLen; + *srcLen = *destLen = 0; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + + LzmaDec_Construct(&p); + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); + if (res != 0) + return res; + p.dic = dest; + p.dicBufSize = outSize; + + LzmaDec_Init(&p); + + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + + (*destLen) = p.dicPos; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.h new file mode 100644 index 000000000..98cdbe949 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaDec.h @@ -0,0 +1,223 @@ +/* LzmaDec.h -- LZMA Decoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMADEC_H +#define __LZMADEC_H + +#include "Types.h" + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Constr() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.c new file mode 100644 index 000000000..492b78510 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.c @@ -0,0 +1,2281 @@ +/* LzmaEnc.c -- LZMA Encoder +2009-02-02 : Igor Pavlov : Public domain */ + +#include + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#if defined(SHOW_STAT) || defined(SHOW_STAT2) +#include +#endif + +#include "LzmaEnc.h" + +#include "LzFind.h" +#ifdef COMPRESS_MF_MT +#include "LzFindMt.h" +#endif + +#ifdef SHOW_STAT +static int ttt = 0; +#endif + +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) + +#define kBlockSize (9 << 10) +#define kUnpackBlockSize (1 << 18) +#define kMatchArraySize (1 << 21) +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) + +#define kNumMaxDirectBits (31) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +#define kBitPrice (1 << kNumBitPriceShiftBits) + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = 4; + if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); + if (p->numThreads < 0) + p->numThreads = + #ifdef COMPRESS_MF_MT + ((p->btMode && p->algo) ? 2 : 1); + #else + 1; + #endif +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + +/* #define LZMA_LOG_BSR */ +/* Define it for Intel's CPU */ + + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 30 + +#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } + +static UInt32 GetPosSlot1(UInt32 pos) +{ + UInt32 res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + +#else + +#define kNumLogBits (9 + (int)sizeof(size_t) / 2) +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + int c = 2, slotFast; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) + { + UInt32 k = (1 << ((slotFast >> 1) - 1)); + UInt32 j; + for (j = 0; j < k; j++, c++) + g_FastPos[c] = (Byte)slotFast; + } +} + +#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> i] + (i * 2); } +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef unsigned CState; + +typedef struct _COptimal +{ + UInt32 price; + + CState state; + int prev1IsChar; + int prev2; + + UInt32 posPrev2; + UInt32 backPrev2; + + UInt32 posPrev; + UInt32 backPrev; + UInt32 backs[LZMA_NUM_REPS]; +} COptimal; + +#define kNumOpts (1 << 12) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +#define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) + +#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + +typedef struct +{ + CLzmaProb choice; + CLzmaProb choice2; + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; + CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + +typedef struct +{ + CLenEnc p; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + UInt32 tableSize; + UInt32 counters[LZMA_NUM_PB_STATES_MAX]; +} CLenPriceEnc; + +typedef struct _CRangeEnc +{ + UInt32 range; + Byte cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + +typedef struct _CSeqInStreamBuf +{ + ISeqInStream funcTable; + const Byte *data; + SizeT rem; +} CSeqInStreamBuf; + +static SRes MyRead(void *pp, void *data, size_t *size) +{ + size_t curSize = *size; + CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; + if (p->rem < curSize) + curSize = p->rem; + memcpy(data, p->data, curSize); + p->rem -= curSize; + p->data += curSize; + *size = curSize; + return SZ_OK; +} + +typedef struct +{ + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; +} CSaveState; + +typedef struct _CLzmaEnc +{ + IMatchFinder matchFinder; + void *matchFinderObj; + + #ifdef COMPRESS_MF_MT + Bool mtMode; + CMatchFinderMt matchFinderMt; + #endif + + CMatchFinder matchFinderBase; + + #ifdef COMPRESS_MF_MT + Byte pad[128]; + #endif + + UInt32 optimumEndIndex; + UInt32 optimumCurrentIndex; + + UInt32 longestMatchLength; + UInt32 numPairs; + UInt32 numAvail; + COptimal opt[kNumOpts]; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + UInt32 numFastBytes; + UInt32 additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; + + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + UInt32 alignPrices[kAlignTableSize]; + UInt32 alignPriceCount; + + UInt32 distTableSize; + + unsigned lc, lp, pb; + unsigned lpMask, pbMask; + + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + unsigned lclp; + + Bool fastMode; + + CRangeEnc rc; + + Bool writeEndMark; + UInt64 nowPos64; + UInt32 matchPriceCount; + Bool finished; + Bool multiThread; + + SRes result; + UInt32 dictSize; + UInt32 matchFinderCycles; + + ISeqInStream *inStream; + CSeqInStreamBuf seqBufInStream; + + CSaveState saveState; +} CLzmaEnc; + +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); +} + +void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); +} + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || + props.dictSize > (1U << kDicLogSizeMaxCompress) || props.dictSize > (1U << 30)) + return SZ_ERROR_PARAM; + p->dictSize = props.dictSize; + p->matchFinderCycles = props.mc; + { + unsigned fb = props.fb; + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = props.lc; + p->lp = props.lp; + p->pb = props.pb; + p->fastMode = (props.algo == 0); + p->matchFinderBase.btMode = props.btMode; + { + UInt32 numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) + numHashBytes = 2; + else if (props.numHashBytes < 4) + numHashBytes = props.numHashBytes; + } + p->matchFinderBase.numHashBytes = numHashBytes; + } + + p->matchFinderBase.cutValue = props.mc; + + p->writeEndMark = props.writeEndMark; + + #ifdef COMPRESS_MF_MT + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + #endif + + return SZ_OK; +} + +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsCharState(s) ((s) < 7) + +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = 0; + p->bufBase = 0; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) +{ + if (p->bufBase == 0) + { + p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); + if (p->bufBase == 0) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->low = 0; + p->range = 0xFFFFFFFF; + p->cacheSize = 1; + p->cache = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = p->buf - p->bufBase; + if (num != p->outStream->Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) + { + Byte temp = p->cache; + do + { + Byte *buf = p->buf; + *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + temp = 0xFF; + } + while (--p->cacheSize != 0); + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) +{ + do + { + p->range >>= 1; + p->low += p->range & (0 - ((value >> --numBits) & 1)); + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } + } + while (numBits != 0); +} + +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) +{ + UInt32 ttt = *prob; + UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; + if (symbol == 0) + { + p->range = newBound; + ttt += (kBitModelTotal - ttt) >> kNumMoveBits; + } + else + { + p->low += newBound; + p->range -= newBound; + ttt -= ttt >> kNumMoveBits; + } + *prob = (CLzmaProb)ttt; + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +{ + symbol |= 0x100; + do + { + RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +{ + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); +} + +void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +{ + UInt32 i; + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) + { + const int kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = i; + UInt32 bitCount = 0; + int j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + } +} + + +#define GET_PRICE(prob, symbol) \ + p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, symbol) \ + ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= 0x100; + do + { + price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); + return price; +} + +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); + return price; +} + + +static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0;) + { + UInt32 bit; + i--; + bit = (symbol >> i) & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + } +} + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = 0; i < numBitLevels; i++) + { + UInt32 bit = symbol & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } +} + +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= (1 << numBitLevels); + while (symbol != 1) + { + price += GET_PRICEa(probs[symbol >> 1], symbol & 1); + symbol >>= 1; + } + return price; +} + +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) | bit; + } + return price; +} + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + p->choice = p->choice2 = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) + p->mid[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) +{ + if (symbol < kLenNumLowSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice, 0); + RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice, 1); + if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice2, 0); + RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice2, 1); + RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); + } + } +} + +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) +{ + UInt32 a0 = GET_PRICE_0a(p->choice); + UInt32 a1 = GET_PRICE_1a(p->choice); + UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); + UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); + UInt32 i = 0; + for (i = 0; i < kLenNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); + } + for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); + } + for (; i < numSymbols; i++) + prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); +} + +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) +{ + LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); + p->counters[posState] = p->tableSize; +} + +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) +{ + UInt32 posState; + for (posState = 0; posState < numPosStates; posState++) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) +{ + LenEnc_Encode(&p->p, rc, symbol, posState); + if (updatePrice) + if (--p->counters[posState] == 0) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + + + + +static void MovePos(CLzmaEnc *p, UInt32 num) +{ + #ifdef SHOW_STAT + ttt += num; + printf("\n MovePos %d", num); + #endif + if (num != 0) + { + p->additionalOffset += num; + p->matchFinder.Skip(p->matchFinderObj, num); + } +} + +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) +{ + UInt32 lenRes = 0, numPairs; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + #ifdef SHOW_STAT + printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); + ttt++; + { + UInt32 i; + for (i = 0; i < numPairs; i += 2) + printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); + } + #endif + if (numPairs > 0) + { + lenRes = p->matches[numPairs - 2]; + if (lenRes == p->numFastBytes) + { + const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + UInt32 distance = p->matches[numPairs - 1] + 1; + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *pby2 = pby - distance; + for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); + } + } + } + p->additionalOffset++; + *numDistancePairsRes = numPairs; + return lenRes; +} + + +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; +#define IsShortRep(p) ((p)->backPrev == 0) + +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) +{ + return + GET_PRICE_0(p->isRepG0[state]) + + GET_PRICE_0(p->isRep0Long[state][posState]); +} + +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) +{ + UInt32 price; + if (repIndex == 0) + { + price = GET_PRICE_0(p->isRepG0[state]); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(p->isRepG0[state]); + if (repIndex == 1) + price += GET_PRICE_0(p->isRepG1[state]); + else + { + price += GET_PRICE_1(p->isRepG1[state]); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) +{ + return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + + GetPureRepPrice(p, repIndex, state, posState); +} + +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) +{ + UInt32 posMem = p->opt[cur].posPrev; + UInt32 backMem = p->opt[cur].backPrev; + p->optimumEndIndex = cur; + do + { + if (p->opt[cur].prev1IsChar) + { + MakeAsChar(&p->opt[posMem]) + p->opt[posMem].posPrev = posMem - 1; + if (p->opt[cur].prev2) + { + p->opt[posMem - 1].prev1IsChar = False; + p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; + p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; + } + } + { + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = p->opt[posPrev].backPrev; + posMem = p->opt[posPrev].posPrev; + + p->opt[posPrev].backPrev = backCur; + p->opt[posPrev].posPrev = cur; + cur = posPrev; + } + } + while (cur != 0); + *backRes = p->opt[0].backPrev; + p->optimumCurrentIndex = p->opt[0].posPrev; + return p->optimumCurrentIndex; +} + +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) + +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; + UInt32 matchPrice, repMatchPrice, normalMatchPrice; + UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; + UInt32 *matches; + const Byte *data; + Byte curByte, matchByte; + if (p->optimumEndIndex != p->optimumCurrentIndex) + { + const COptimal *opt = &p->opt[p->optimumCurrentIndex]; + UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; + *backRes = opt->backPrev; + p->optimumCurrentIndex = opt->posPrev; + return lenRes; + } + p->optimumCurrentIndex = p->optimumEndIndex = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + *backRes = (UInt32)(-1); + return 1; + } + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repMaxIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 lenTest; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - (reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= p->numFastBytes) + { + UInt32 lenRes; + *backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + MovePos(p, lenRes - 1); + return lenRes; + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) + { + *backRes = (UInt32)-1; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + + (!IsCharState(p->state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + MakeAsChar(&p->opt[1]); + + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); + + if (matchByte == curByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAsShortRep(&p->opt[1]); + } + } + lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + *backRes = p->opt[1].backPrev; + return 1; + } + + p->opt[1].posPrev = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + p->opt[0].backs[i] = reps[i]; + + len = lenEnd; + do + p->opt[len--].price = kInfinityPrice; + while (len >= 2); + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; + COptimal *opt = &p->opt[repLen]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = i; + opt->prev1IsChar = False; + } + } + while (--repLen >= 2); + } + + normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= mainLen) + { + UInt32 offs = 0; + while (len > matches[offs]) + offs += 2; + for (; ; len++) + { + COptimal *opt; + UInt32 distance = matches[offs + 1]; + + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(len); + if (distance < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][distance]; + else + { + UInt32 slot; + GetPosSlot2(distance, slot); + curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; + } + opt = &p->opt[len]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = distance + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + if (len == matches[offs]) + { + offs += 2; + if (offs == numPairs) + break; + } + } + } + + cur = 0; + + #ifdef SHOW_STAT2 + if (position >= 0) + { + unsigned i; + printf("\n pos = %4X", position); + for (i = cur; i <= lenEnd; i++) + printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); + } + #endif + + for (;;) + { + UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; + UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; + Bool nextIsChar; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt; + COptimal *nextOpt; + + cur++; + if (cur == lenEnd) + return Backward(p, backRes, cur); + + newLen = ReadMatchDistances(p, &numPairs); + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLength = newLen; + return Backward(p, backRes, cur); + } + position++; + curOpt = &p->opt[cur]; + posPrev = curOpt->posPrev; + if (curOpt->prev1IsChar) + { + posPrev--; + if (curOpt->prev2) + { + state = p->opt[curOpt->posPrev2].state; + if (curOpt->backPrev2 < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + else + state = p->opt[posPrev].state; + state = kLiteralNextStates[state]; + } + else + state = p->opt[posPrev].state; + if (posPrev == cur - 1) + { + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + UInt32 pos; + const COptimal *prevOpt; + if (curOpt->prev1IsChar && curOpt->prev2) + { + posPrev = curOpt->posPrev2; + pos = curOpt->backPrev2; + state = kRepNextStates[state]; + } + else + { + pos = curOpt->backPrev; + if (pos < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + prevOpt = &p->opt[posPrev]; + if (pos < LZMA_NUM_REPS) + { + UInt32 i; + reps[0] = prevOpt->backs[pos]; + for (i = 1; i <= pos; i++) + reps[i] = prevOpt->backs[i - 1]; + for (; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i]; + } + else + { + UInt32 i; + reps[0] = (pos - LZMA_NUM_REPS); + for (i = 1; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i - 1]; + } + } + curOpt->state = (CState)state; + + curOpt->backs[0] = reps[0]; + curOpt->backs[1] = reps[1]; + curOpt->backs[2] = reps[2]; + curOpt->backs[3] = reps[3]; + + curPrice = curOpt->price; + nextIsChar = False; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + posState = (position & p->pbMask); + + curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + curAnd1Price += + (!IsCharState(state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + nextOpt = &p->opt[cur + 1]; + + if (curAnd1Price < nextOpt->price) + { + nextOpt->price = curAnd1Price; + nextOpt->posPrev = cur; + MakeAsChar(nextOpt); + nextIsChar = True; + } + + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); + if (shortRepPrice <= nextOpt->price) + { + nextOpt->price = shortRepPrice; + nextOpt->posPrev = cur; + MakeAsShortRep(nextOpt); + nextIsChar = True; + } + } + numAvailFull = p->numAvail; + { + UInt32 temp = kNumOpts - 1 - cur; + if (temp < numAvailFull) + numAvailFull = temp; + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + if (!nextIsChar && matchByte != curByte) /* speed optimization */ + { + /* try Literal + rep0 */ + UInt32 temp; + UInt32 lenTest2; + const Byte *data2 = data - (reps[0] + 1); + UInt32 limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + + for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); + lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kLiteralNextStates[state]; + UInt32 posStateNext = (position + 1) & p->pbMask; + UInt32 nextRepMatchPrice = curAnd1Price + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = False; + } + } + } + } + + startLen = 2; /* speed optimization */ + { + UInt32 repIndex; + for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) + { + UInt32 lenTest; + UInt32 lenTestTemp; + UInt32 price; + const Byte *data2 = data - (reps[repIndex] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + while (lenEnd < cur + lenTest) + p->opt[++lenEnd].price = kInfinityPrice; + lenTestTemp = lenTest; + price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; + COptimal *opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = repIndex; + opt->prev1IsChar = False; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + /* if (_maxMode) */ + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kRepNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = + price + p->repLenEnc.prices[posState][lenTest - 2] + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (position + lenTest + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + lenTest + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = repIndex; + } + } + } + } + } + } + /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ + if (newLen > numAvail) + { + newLen = numAvail; + for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); + matches[numPairs] = newLen; + numPairs += 2; + } + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 offs, curBack, posSlot; + UInt32 lenTest; + while (lenEnd < cur + newLen) + p->opt[++lenEnd].price = kInfinityPrice; + + offs = 0; + while (startLen > matches[offs]) + offs += 2; + curBack = matches[offs + 1]; + GetPosSlot2(curBack, posSlot); + for (lenTest = /*2*/ startLen; ; lenTest++) + { + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(lenTest); + COptimal *opt; + if (curBack < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; + + opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = curBack + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + + if (/*_maxMode && */lenTest == matches[offs]) + { + /* Try Match + Literal + Rep0 */ + const Byte *data2 = data - (curBack + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kMatchNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (posStateNext + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + UInt32 curAndLenPrice; + COptimal *opt; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = curBack + LZMA_NUM_REPS; + } + } + } + offs += 2; + if (offs == numPairs) + break; + curBack = matches[offs + 1]; + if (curBack >= kNumFullDistances) + GetPosSlot2(curBack, posSlot); + } + } + } + } +} + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; + const Byte *data; + const UInt32 *matches; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + *backRes = (UInt32)-1; + if (numAvail < 2) + return 1; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + + repLen = repIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + if (len >= p->numFastBytes) + { + *backRes = i; + MovePos(p, len - 1); + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + + mainDist = 0; /* for GCC */ + if (mainLen >= 2) + { + mainDist = matches[numPairs - 1]; + while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) + { + if (!ChangePair(matches[numPairs - 3], mainDist)) + break; + numPairs -= 2; + mainLen = matches[numPairs - 2]; + mainDist = matches[numPairs - 1]; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2 && ( + (repLen + 1 >= mainLen) || + (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || + (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) + { + *backRes = repIndex; + MovePos(p, repLen - 1); + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); + if (p->longestMatchLength >= 2) + { + UInt32 newDistance = matches[p->numPairs - 1]; + if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || + (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || + (p->longestMatchLength > mainLen + 1) || + (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) + return 1; + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len, limit; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2; len < limit && data[len] == data2[len]; len++); + if (len >= limit) + return 1; + } + *backRes = mainDist + LZMA_NUM_REPS; + MovePos(p, mainLen - 2); + return mainLen; +} + +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) +{ + UInt32 len; + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + len = LZMA_MATCH_LEN_MIN; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); + RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); +} + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + if (p->matchFinderBase.result != SZ_OK) + p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + +static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + +static void FillAlignPrices(CLzmaEnc *p) +{ + UInt32 i; + for (i = 0; i < kAlignTableSize; i++) + p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + p->alignPriceCount = 0; +} + +static void FillDistancesPrices(CLzmaEnc *p) +{ + UInt32 tempPrices[kNumFullDistances]; + UInt32 i, lenToPosState; + for (i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot1(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); + } + + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); + for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + + { + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; + UInt32 i; + for (i = 0; i < kStartPosModelIndex; i++) + distancesPrices[i] = posSlotPrices[i]; + for (; i < kNumFullDistances; i++) + distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; + } + } + p->matchPriceCount = 0; +} + +void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); + #ifdef COMPRESS_MF_MT + MatchFinderMt_Construct(&p->matchFinderMt); + p->matchFinderMt.MatchFinder = &p->matchFinderBase; + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) +{ + void *p; + p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); + if (p != 0) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->litProbs); + alloc->Free(alloc, p->saveState.litProbs); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + #ifdef COMPRESS_MF_MT + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + alloc->Free(alloc, p); +} + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->inStream != 0) + { + p->matchFinderBase.stream = p->inStream; + p->matchFinder.Init(p->matchFinderObj); + p->inStream = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + UInt32 numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); + p->state = kLiteralNextStates[p->state]; + curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + for (;;) + { + UInt32 pos, len, posState; + + if (p->fastMode) + len = GetOptimumFast(p, &pos); + else + len = GetOptimum(p, nowPos32, &pos); + + #ifdef SHOW_STAT2 + printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); + #endif + + posState = nowPos32 & p->pbMask; + if (len == 1 && pos == (UInt32)-1) + { + Byte curByte; + CLzmaProb *probs; + const Byte *data; + + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + curByte = *data; + probs = LIT_PROBS(nowPos32, *(data - 1)); + if (IsCharState(p->state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); + p->state = kLiteralNextStates[p->state]; + } + else + { + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + if (pos < LZMA_NUM_REPS) + { + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); + if (pos == 0) + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); + RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = p->reps[pos]; + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); + if (pos == 1) + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); + else + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); + if (pos == 3) + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = distance; + } + if (len == 1) + p->state = kShortRepNextStates[p->state]; + else + { + LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + p->state = kRepNextStates[p->state]; + } + } + else + { + UInt32 posSlot; + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + pos -= LZMA_NUM_REPS; + GetPosSlot(pos, posSlot); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); + else + { + RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + p->alignPriceCount++; + } + } + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = pos; + p->matchPriceCount++; + } + } + p->additionalOffset -= len; + nowPos32 += len; + if (p->additionalOffset == 0) + { + UInt32 processed; + if (!p->fastMode) + { + if (p->matchPriceCount >= (1 << 7)) + FillDistancesPrices(p); + if (p->alignPriceCount >= kAlignTableSize) + FillAlignPrices(p); + } + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + if (useLimits) + { + if (processed + kNumOpts + 300 >= maxUnpackSize || + RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) + break; + } + else if (processed >= (1 << 15)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 beforeSize = kNumOpts; + Bool btMode; + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + btMode = (p->matchFinderBase.btMode != 0); + #ifdef COMPRESS_MF_MT + p->mtMode = (p->multiThread && !p->fastMode && btMode); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + if (p->litProbs == 0 || p->saveState.litProbs == 0) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); + + if (beforeSize + p->dictSize < keepWindowSize) + beforeSize = keepWindowSize - p->dictSize; + + #ifdef COMPRESS_MF_MT + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); + p->matchFinderObj = &p->matchFinderMt; + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &p->matchFinderBase; + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + } + return SZ_OK; +} + +void LzmaEnc_Init(CLzmaEnc *p) +{ + UInt32 i; + p->state = 0; + for (i = 0 ; i < LZMA_NUM_REPS; i++) + p->reps[i] = 0; + + RangeEnc_Init(&p->rc); + + + for (i = 0; i < kNumStates; i++) + { + UInt32 j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + UInt32 num = 0x300 << (p->lp + p->lc); + for (i = 0; i < num; i++) + p->litProbs[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + UInt32 j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + p->posEncoders[i] = kProbInitValue; + } + + LenEnc_Init(&p->lenEnc.p); + LenEnc_Init(&p->repLenEnc.p); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + p->optimumEndIndex = 0; + p->optimumCurrentIndex = 0; + p->additionalOffset = 0; + + p->pbMask = (1 << p->pb) - 1; + p->lpMask = (1 << p->lp) - 1; +} + +void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 i; + for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->inStream = inStream; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, + ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->inStream = inStream; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + p->seqBufInStream.funcTable.Read = MyRead; + p->seqBufInStream.data = src; + p->seqBufInStream.rem = srcLen; +} + +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->inStream = &p->seqBufInStream.funcTable; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifdef COMPRESS_MF_MT + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + pp = pp; + #endif +} + +typedef struct _CSeqOutStreamBuf +{ + ISeqOutStream funcTable; + Byte *data; + SizeT rem; + Bool overflow; +} CSeqOutStreamBuf; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + + +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +} + +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +} + +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + UInt64 nowPos64; + SRes res; + CSeqOutStreamBuf outStream; + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = False; + p->finished = False; + p->result = SZ_OK; + + if (reInit) + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + nowPos64 = p->nowPos64; + RangeEnc_Init(&p->rc); + p->rc.outStream = &outStream.funcTable; + + res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); + + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + + return res; +} + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + SRes res = SZ_OK; + + #ifdef COMPRESS_MF_MT + Byte allocaDummy[0x300]; + int i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)i; + #endif + + RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, False, 0, 0); + if (res != SZ_OK || p->finished != 0) + break; + if (progress != 0) + { + res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + LzmaEnc_Finish(pp); + return res; +} + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + int i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)2 << i)) + { + dictSize = (2 << i); + break; + } + if (dictSize <= ((UInt32)3 << i)) + { + dictSize = (3 << i); + break; + } + } + + for (i = 0; i < 4; i++) + props[1 + i] = (Byte)(dictSize >> (8 * i)); + return SZ_OK; +} + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CSeqOutStreamBuf outStream; + + LzmaEnc_SetInputBuf(p, src, srcLen); + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, + progress, alloc, allocBig); + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (p == 0) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.h new file mode 100644 index 000000000..bfbc7d2b9 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaEnc.h @@ -0,0 +1,72 @@ +/* LzmaEnc.h -- LZMA Encoder +2008-10-04 : Igor Pavlov : Public domain */ + +#ifndef __LZMAENC_H +#define __LZMAENC_H + +#include "Types.h" + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaEncProps +{ + int level; /* 0 <= level <= 9 */ + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + (1 << 12) <= dictSize <= (1 << 30) for 64-bit version + default = (1 << 24) */ + int lc; /* 0 <= lc <= 8, default = 3 */ + int lp; /* 0 <= lp <= 4, default = 0 */ + int pb; /* 0 <= pb <= 4, default = 2 */ + int algo; /* 0 - fast, 1 - normal, default = 1 */ + int fb; /* 5 <= fb <= 273, default = 32 */ + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ + int numHashBytes; /* 2, 3 or 4, default = 4 */ + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ + int numThreads; /* 1 or 2, default = 2 */ +} CLzmaEncProps; + +void LzmaEncProps_Init(CLzmaEncProps *p); +void LzmaEncProps_Normalize(CLzmaEncProps *p); +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); + + +/* ---------- CLzmaEncHandle Interface ---------- */ + +/* LzmaEnc_* functions can return the following exit codes: +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - Write callback error. + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +/* ---------- One Call Interface ---------- */ + +/* LzmaEncode +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.c b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.c new file mode 100644 index 000000000..6cc29da23 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.c @@ -0,0 +1,48 @@ +/* LzmaLib.c -- LZMA library wrapper +2008-08-05 +Igor Pavlov +Public domain */ + +#include "LzmaEnc.h" +#include "LzmaDec.h" +#include "Alloc.h" +#include "LzmaLib.h" + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads, /* 1 or 2, default = 2 */ + int algo /* 0 = fast, 1 = normal */ +) +{ + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + props.lc = lc; + props.lp = lp; + props.pb = pb; + props.fb = fb; + props.numThreads = numThreads; + props.algo = algo; + + return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); +} + + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, + const unsigned char *props, size_t propsSize) +{ + ELzmaStatus status; + return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); +} diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.h b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.h new file mode 100644 index 000000000..8ace8bd75 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/LzmaLib.h @@ -0,0 +1,136 @@ +/* LzmaLib.h -- LZMA library interface +2008-08-05 +Igor Pavlov +Public domain */ + +#ifndef __LZMALIB_H +#define __LZMALIB_H + +#include "Types.h" + +#ifdef __cplusplus + #define MY_EXTERN_C extern "C" +#else + #define MY_EXTERN_C extern +#endif + +#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL + +#define LZMA_PROPS_SIZE 5 + +/* +RAM requirements for LZMA: + for compression: (dictSize * 11.5 + 6 MB) + state_size + for decompression: dictSize + state_size + state_size = (4 + (1.5 << (lc + lp))) KB + by default (lc=3, lp=0), state_size = 16 KB. + +LZMA properties (5 bytes) format + Offset Size Description + 0 1 lc, lp and pb in encoded form. + 1 4 dictSize (little endian). +*/ + +/* +LzmaCompress +------------ + +outPropsSize - + In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + + LZMA Encoder will use defult values for any parameter, if it is + -1 for any from: level, loc, lp, pb, fb, numThreads + 0 for dictSize + +level - compression level: 0 <= level <= 9; + + level dictSize algo fb + 0: 16 KB 0 32 + 1: 64 KB 0 32 + 2: 256 KB 0 32 + 3: 1 MB 0 32 + 4: 4 MB 0 32 + 5: 16 MB 1 32 + 6: 32 MB 1 32 + 7+: 64 MB 1 64 + + The default value for "level" is 5. + + algo = 0 means fast method + algo = 1 means normal method + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + +lc - The number of literal context bits (high bits of previous literal). + It can be in the range from 0 to 8. The default value is 3. + Sometimes lc=4 gives the gain for big files. + +lp - The number of literal pos bits (low bits of current position for literals). + It can be in the range from 0 to 4. The default value is 0. + The lp switch is intended for periodical data when the period is equal to 2^lp. + For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's + better to set lc=0, if you change lp switch. + +pb - The number of pos bits (low bits of current position). + It can be in the range from 0 to 4. The default value is 2. + The pb switch is intended for periodical data when the period is equal 2^pb. + +fb - Word size (the number of fast bytes). + It can be in the range from 5 to 273. The default value is 32. + Usually, a big number gives a little bit better compression ratio and + slower compression process. + +numThreads - The number of thereads. 1 or 2. The default value is 2. + Fast mode (algo = 0) can use only 1 thread. + +Out: + destLen - processed output size +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* default = (1 << 24) */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads, /* 1 or 2, default = 2 */ + int algo /* 0 = fast, 1 = normal, default = 0 for level < 5, 1 for level >= 5 */ + ); + +/* +LzmaUncompress +-------------- +In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size +Out: + destLen - processed output size + srcLen - processed input size +Returns: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation arror + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) +*/ + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, + const unsigned char *props, size_t propsSize); + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/NameMangle.h b/src/external/OpenCTM-1.0.3/lib/liblzma/NameMangle.h new file mode 100644 index 000000000..669d3c4ac --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/NameMangle.h @@ -0,0 +1,84 @@ +/* NameMangle.h -- Name mangling to avoid linking conflicts +2009-04-15 : Marcus Geelnard : Public domain */ + +#ifndef __7Z_NAMEMANGLE_H +#define __7Z_NAMEMANGLE_H + +#ifdef LZMA_PREFIX_CTM + +/* Alloc.c */ +#define MyAlloc _ctm_MyAlloc +#define MyFree _ctm_MyFree +#ifdef _WIN32 +#define MidAlloc _ctm_MidAlloc +#define MidFree _ctm_MidFree +#define SetLargePageSize _ctm_SetLargePageSize +#define BigAlloc _ctm_BigAlloc +#define BigFree _ctm_BigFree +#endif /* _WIN32 */ + +/* LzFind.c */ +#define MatchFinder_GetPointerToCurrentPos _ctm_MatchFinder_GetPointerToCurrentPos +#define MatchFinder_GetIndexByte _ctm_MatchFinder_GetIndexByte +#define MatchFinder_GetNumAvailableBytes _ctm_MatchFinder_GetNumAvailableBytes +#define MatchFinder_ReduceOffsets _ctm_MatchFinder_ReduceOffsets +#define MatchFinder_MoveBlock _ctm_MatchFinder_MoveBlock +#define MatchFinder_NeedMove _ctm_MatchFinder_NeedMove +#define MatchFinder_ReadIfRequired _ctm_MatchFinder_ReadIfRequired +#define MatchFinder_Construct _ctm_MatchFinder_Construct +#define MatchFinder_Free _ctm_MatchFinder_Free +#define MatchFinder_Create _ctm_MatchFinder_Create +#define MatchFinder_Init _ctm_MatchFinder_Init +#define MatchFinder_Normalize3 _ctm_MatchFinder_Normalize3 +#define GetMatchesSpec1 _ctm_GetMatchesSpec1 +#define Bt3Zip_MatchFinder_GetMatches _ctm_Bt3Zip_MatchFinder_GetMatches +#define Hc3Zip_MatchFinder_GetMatches _ctm_Hc3Zip_MatchFinder_GetMatches +#define Bt3Zip_MatchFinder_Skip _ctm_Bt3Zip_MatchFinder_Skip +#define Hc3Zip_MatchFinder_Skip _ctm_Hc3Zip_MatchFinder_Skip +#define MatchFinder_CreateVTable _ctm_MatchFinder_CreateVTable + +/* LzmaDec.c */ +#define LzmaDec_InitDicAndState _ctm_LzmaDec_InitDicAndState +#define LzmaDec_Init _ctm_LzmaDec_Init +#define LzmaDec_DecodeToDic _ctm_LzmaDec_DecodeToDic +#define LzmaDec_DecodeToBuf _ctm_LzmaDec_DecodeToBuf +#define LzmaDec_FreeProbs _ctm_LzmaDec_FreeProbs +#define LzmaDec_Free _ctm_LzmaDec_Free +#define LzmaProps_Decode _ctm_LzmaProps_Decode +#define LzmaDec_AllocateProbs _ctm_LzmaDec_AllocateProbs +#define LzmaDec_Allocate _ctm_LzmaDec_Allocate +#define LzmaDecode _ctm_LzmaDecode + +/* LzmaEnc.c */ +#define LzmaEncProps_Init _ctm_LzmaEncProps_Init +#define LzmaEncProps_Normalize _ctm_LzmaEncProps_Normalize +#define LzmaEncProps_GetDictSize _ctm_LzmaEncProps_GetDictSize +#define LzmaEnc_FastPosInit _ctm_LzmaEnc_FastPosInit +#define LzmaEnc_SaveState _ctm_LzmaEnc_SaveState +#define LzmaEnc_RestoreState _ctm_LzmaEnc_RestoreState +#define LzmaEnc_SetProps _ctm_LzmaEnc_SetProps +#define LzmaEnc_InitPriceTables _ctm_LzmaEnc_InitPriceTables +#define LzmaEnc_Construct _ctm_LzmaEnc_Construct +#define LzmaEnc_Create _ctm_LzmaEnc_Create +#define LzmaEnc_FreeLits _ctm_LzmaEnc_FreeLits +#define LzmaEnc_Destruct _ctm_LzmaEnc_Destruct +#define LzmaEnc_Destroy _ctm_LzmaEnc_Destroy +#define LzmaEnc_Init _ctm_LzmaEnc_Init +#define LzmaEnc_InitPrices _ctm_LzmaEnc_InitPrices +#define LzmaEnc_PrepareForLzma2 _ctm_LzmaEnc_PrepareForLzma2 +#define LzmaEnc_MemPrepare _ctm_LzmaEnc_MemPrepare +#define LzmaEnc_Finish _ctm_LzmaEnc_Finish +#define LzmaEnc_GetNumAvailableBytes _ctm_LzmaEnc_GetNumAvailableBytes +#define LzmaEnc_GetCurBuf _ctm_LzmaEnc_GetCurBuf +#define LzmaEnc_CodeOneMemBlock _ctm_LzmaEnc_CodeOneMemBlock +#define LzmaEnc_Encode _ctm_LzmaEnc_Encode +#define LzmaEnc_WriteProperties _ctm_LzmaEnc_WriteProperties +#define LzmaEnc_MemEncode _ctm_LzmaEnc_MemEncode + +/* LzmaLib.c */ +#define LzmaCompress _ctm_LzmaCompress +#define LzmaUncompress _ctm_LzmaUncompress + +#endif /* LZMA_PREFIX_CTM */ + +#endif /* __7Z_NAMEMANGLE_H */ diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/Types.h b/src/external/OpenCTM-1.0.3/lib/liblzma/Types.h new file mode 100644 index 000000000..ea00a9f8a --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/Types.h @@ -0,0 +1,210 @@ +/* Types.h -- Basic types +2008-11-23 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#include + +#ifdef _WIN32 +#include +#endif + +#include "NameMangle.h" + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_STD_CALL __stdcall +#define MY_FAST_CALL MY_NO_INLINE __fastcall + +#else + +#define MY_CDECL +#define MY_STD_CALL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#endif diff --git a/src/external/OpenCTM-1.0.3/lib/liblzma/readme.txt b/src/external/OpenCTM-1.0.3/lib/liblzma/readme.txt new file mode 100644 index 000000000..8198e6601 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/liblzma/readme.txt @@ -0,0 +1,7 @@ +This is the C library implementation of LZMA compression/decompression by Igor Pavlov. + +Author: Igor Pavlov +License: Public domain +Version: 4.65 (2009-02-03) + +Some administrative adaptations for integration in OpenCTM were made by Marcus Geelnard. diff --git a/src/external/OpenCTM-1.0.3/lib/openctm-mingw1.def b/src/external/OpenCTM-1.0.3/lib/openctm-mingw1.def new file mode 100644 index 000000000..e3b281070 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/openctm-mingw1.def @@ -0,0 +1,32 @@ +LIBRARY openctm.dll +EXPORTS + ctmAddAttribMap = ctmAddAttribMap@12 @1 + ctmAddUVMap = ctmAddUVMap@16 @2 + ctmAttribPrecision = ctmAttribPrecision@12 @3 + ctmCompressionLevel = ctmCompressionLevel@8 @4 + ctmCompressionMethod = ctmCompressionMethod@8 @5 + ctmDefineMesh = ctmDefineMesh@24 @6 + ctmFileComment = ctmFileComment@8 @7 + ctmFreeContext = ctmFreeContext@4 @8 + ctmGetAttribMapFloat = ctmGetAttribMapFloat@12 @9 + ctmGetAttribMapString = ctmGetAttribMapString@12 @10 + ctmGetError = ctmGetError@4 @11 + ctmGetFloat = ctmGetFloat@8 @12 + ctmGetFloatArray = ctmGetFloatArray@8 @13 + ctmGetInteger = ctmGetInteger@8 @14 + ctmGetIntegerArray = ctmGetIntegerArray@8 @15 + ctmGetNamedAttribMap = ctmGetNamedAttribMap@8 @16 + ctmGetNamedUVMap = ctmGetNamedUVMap@8 @17 + ctmGetString = ctmGetString@8 @18 + ctmGetUVMapFloat = ctmGetUVMapFloat@12 @19 + ctmGetUVMapString = ctmGetUVMapString@12 @20 + ctmErrorString = ctmErrorString@4 @21 + ctmLoad = ctmLoad@8 @22 + ctmLoadCustom = ctmLoadCustom@12 @23 + ctmNewContext = ctmNewContext@4 @24 + ctmNormalPrecision = ctmNormalPrecision@8 @25 + ctmSave = ctmSave@8 @26 + ctmSaveCustom = ctmSaveCustom@12 @27 + ctmUVCoordPrecision = ctmUVCoordPrecision@12 @28 + ctmVertexPrecision = ctmVertexPrecision@8 @29 + ctmVertexPrecisionRel = ctmVertexPrecisionRel@8 @30 diff --git a/src/external/OpenCTM-1.0.3/lib/openctm-mingw2.def b/src/external/OpenCTM-1.0.3/lib/openctm-mingw2.def new file mode 100644 index 000000000..8eb12f6fd --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/openctm-mingw2.def @@ -0,0 +1,32 @@ +LIBRARY openctm.dll +EXPORTS + ctmAddAttribMap@12 @1 + ctmAddUVMap@16 @2 + ctmAttribPrecision@12 @3 + ctmCompressionLevel@8 @4 + ctmCompressionMethod@8 @5 + ctmDefineMesh@24 @6 + ctmFileComment@8 @7 + ctmFreeContext@4 @8 + ctmGetAttribMapFloat@12 @9 + ctmGetAttribMapString@12 @10 + ctmGetError@4 @11 + ctmGetFloat@8 @12 + ctmGetFloatArray@8 @13 + ctmGetInteger@8 @14 + ctmGetIntegerArray@8 @15 + ctmGetNamedAttribMap@8 @16 + ctmGetNamedUVMap@8 @17 + ctmGetString@8 @18 + ctmGetUVMapFloat@12 @19 + ctmGetUVMapString@12 @20 + ctmErrorString@4 @21 + ctmLoad@8 @22 + ctmLoadCustom@12 @23 + ctmNewContext@4 @24 + ctmNormalPrecision@8 @25 + ctmSave@8 @26 + ctmSaveCustom@12 @27 + ctmUVCoordPrecision@12 @28 + ctmVertexPrecision@8 @29 + ctmVertexPrecisionRel@8 @30 diff --git a/src/external/OpenCTM-1.0.3/lib/openctm-msvc.def b/src/external/OpenCTM-1.0.3/lib/openctm-msvc.def new file mode 100644 index 000000000..bb66dbdfe --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/openctm-msvc.def @@ -0,0 +1,32 @@ +LIBRARY openctm.dll +EXPORTS + ctmAddAttribMap + ctmAddUVMap + ctmAttribPrecision + ctmCompressionLevel + ctmCompressionMethod + ctmDefineMesh + ctmFileComment + ctmFreeContext + ctmGetAttribMapFloat + ctmGetAttribMapString + ctmGetError + ctmGetFloat + ctmGetFloatArray + ctmGetInteger + ctmGetIntegerArray + ctmGetNamedAttribMap + ctmGetNamedUVMap + ctmGetString + ctmGetUVMapFloat + ctmGetUVMapString + ctmErrorString + ctmLoad + ctmLoadCustom + ctmNewContext + ctmNormalPrecision + ctmSave + ctmSaveCustom + ctmUVCoordPrecision + ctmVertexPrecision + ctmVertexPrecisionRel diff --git a/src/external/OpenCTM-1.0.3/lib/openctm.c b/src/external/OpenCTM-1.0.3/lib/openctm.c new file mode 100644 index 000000000..3c0acd9ef --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/openctm.c @@ -0,0 +1,1423 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: openctm.c +// Description: API functions. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include "openctm.h" +#include "internal.h" + + +// The C99 macro isfinite() is not supported on all platforms (specifically, +// MS Visual Studio does not support C99) +#if !defined(isfinite) && defined(_MSC_VER) + #include + #define isfinite(x) _finite(x) +#endif + + +//----------------------------------------------------------------------------- +// _ctmFreeMapList() - Free a float map list. +//----------------------------------------------------------------------------- +static void _ctmFreeMapList(_CTMcontext * self, _CTMfloatmap * aMapList) +{ + _CTMfloatmap * map, * nextMap; + map = aMapList; + while(map) + { + // Free internally allocated array (if we are in import mode) + if((self->mMode == CTM_IMPORT) && map->mValues) + free(map->mValues); + + // Free map name + if(map->mName) + free(map->mName); + + // Free file name + if(map->mFileName) + free(map->mFileName); + + nextMap = map->mNext; + free(map); + map = nextMap; + } +} + +//----------------------------------------------------------------------------- +// _ctmClearMesh() - Clear the mesh in a CTM context. +//----------------------------------------------------------------------------- +static void _ctmClearMesh(_CTMcontext * self) +{ + // Free internally allocated mesh arrays + if(self->mMode == CTM_IMPORT) + { + if(self->mVertices) + free(self->mVertices); + if(self->mIndices) + free(self->mIndices); + if(self->mNormals) + free(self->mNormals); + } + + // Clear externally assigned mesh arrays + self->mVertices = (CTMfloat *) 0; + self->mVertexCount = 0; + self->mIndices = (CTMuint *) 0; + self->mTriangleCount = 0; + self->mNormals = (CTMfloat *) 0; + + // Free UV coordinate map list + _ctmFreeMapList(self, self->mUVMaps); + self->mUVMaps = (_CTMfloatmap *) 0; + self->mUVMapCount = 0; + + // Free attribute map list + _ctmFreeMapList(self, self->mAttribMaps); + self->mAttribMaps = (_CTMfloatmap *) 0; + self->mAttribMapCount = 0; +} + +//----------------------------------------------------------------------------- +// _ctmCheckMeshIntegrity() - Check if a mesh is valid (i.e. is non-empty, and +// contains valid data). +//----------------------------------------------------------------------------- + +static CTMint _ctmCheckMeshIntegrity(_CTMcontext * self) +{ + CTMuint i; + _CTMfloatmap * map; + + // Check that we have all the mandatory data + if(!self->mVertices || !self->mIndices || (self->mVertexCount < 1) || + (self->mTriangleCount < 1)) + { + return CTM_FALSE; + } + + // Check that all indices are within range + for(i = 0; i < (self->mTriangleCount * 3); ++ i) + { + if(self->mIndices[i] >= self->mVertexCount) + { + return CTM_FALSE; + } + } + + // Check that all vertices are finite (non-NaN, non-inf) + for(i = 0; i < self->mVertexCount * 3; ++ i) + { + if(!isfinite(self->mVertices[i])) + { + return CTM_FALSE; + } + } + + // Check that all normals are finite (non-NaN, non-inf) + if(self->mNormals) + { + for(i = 0; i < self->mVertexCount * 3; ++ i) + { + if(!isfinite(self->mNormals[i])) + { + return CTM_FALSE; + } + } + } + + // Check that all UV maps are finite (non-NaN, non-inf) + map = self->mUVMaps; + while(map) + { + for(i = 0; i < self->mVertexCount * 2; ++ i) + { + if(!isfinite(map->mValues[i])) + { + return CTM_FALSE; + } + } + map = map->mNext; + } + + // Check that all attribute maps are finite (non-NaN, non-inf) + map = self->mAttribMaps; + while(map) + { + for(i = 0; i < self->mVertexCount * 4; ++ i) + { + if(!isfinite(map->mValues[i])) + { + return CTM_FALSE; + } + } + map = map->mNext; + } + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// ctmNewContext() +//----------------------------------------------------------------------------- +CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode) +{ + _CTMcontext * self; + + // Allocate memory for the new structure + self = (_CTMcontext *) malloc(sizeof(_CTMcontext)); + + // Initialize structure (set null pointers and zero array lengths) + memset(self, 0, sizeof(_CTMcontext)); + self->mMode = aMode; + self->mError = CTM_NONE; + self->mMethod = CTM_METHOD_MG1; + self->mCompressionLevel = 1; + self->mVertexPrecision = 1.0f / 1024.0f; + self->mNormalPrecision = 1.0f / 256.0f; + + return (CTMcontext) self; +} + +//----------------------------------------------------------------------------- +// ctmFreeContext() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return; + + // Free all mesh resources + _ctmClearMesh(self); + + // Free the file comment + if(self->mFileComment) + free(self->mFileComment); + + // Free the context + free(self); +} + +//----------------------------------------------------------------------------- +// ctmGetError() +//----------------------------------------------------------------------------- +CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + CTMenum err; + + if(!self) return CTM_INVALID_CONTEXT; + + // Get error code and reset error state + err = self->mError; + self->mError = CTM_NONE; + return err; +} + +//----------------------------------------------------------------------------- +// ctmErrorString() +//----------------------------------------------------------------------------- +CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError) +{ + switch(aError) + { + case CTM_INVALID_CONTEXT: + return "CTM_INVALID_CONTEXT"; + case CTM_INVALID_ARGUMENT: + return "CTM_INVALID_ARGUMENT"; + case CTM_INVALID_OPERATION: + return "CTM_INVALID_OPERATION"; + case CTM_INVALID_MESH: + return "CTM_INVALID_MESH"; + case CTM_OUT_OF_MEMORY: + return "CTM_OUT_OF_MEMORY"; + case CTM_FILE_ERROR: + return "CTM_FILE_ERROR"; + case CTM_BAD_FORMAT: + return "CTM_BAD_FORMAT"; + case CTM_LZMA_ERROR: + return "CTM_LZMA_ERROR"; + case CTM_INTERNAL_ERROR: + return "CTM_INTERNAL_ERROR"; + case CTM_UNSUPPORTED_FORMAT_VERSION: + return "CTM_UNSUPPORTED_FORMAT_VERSION"; + default: + return "Unknown error code"; + } +} + +//----------------------------------------------------------------------------- +// ctmGetInteger() +//----------------------------------------------------------------------------- +CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return 0; + + switch(aProperty) + { + case CTM_VERTEX_COUNT: + return self->mVertexCount; + + case CTM_TRIANGLE_COUNT: + return self->mTriangleCount; + + case CTM_UV_MAP_COUNT: + return self->mUVMapCount; + + case CTM_ATTRIB_MAP_COUNT: + return self->mAttribMapCount; + + case CTM_HAS_NORMALS: + return self->mNormals ? CTM_TRUE : CTM_FALSE; + + case CTM_COMPRESSION_METHOD: + return (CTMuint) self->mMethod; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return 0; +} + +//----------------------------------------------------------------------------- +// ctmGetFloat() +//----------------------------------------------------------------------------- +CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return 0.0f; + + switch(aProperty) + { + case CTM_VERTEX_PRECISION: + return self->mVertexPrecision; + + case CTM_NORMAL_PRECISION: + return self->mNormalPrecision; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return 0.0f; +} + +//----------------------------------------------------------------------------- +// ctmGetIntegerArray() +//----------------------------------------------------------------------------- +CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext, + CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return (CTMuint *) 0; + + switch(aProperty) + { + case CTM_INDICES: + return self->mIndices; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return (CTMuint *) 0; +} + +//----------------------------------------------------------------------------- +// ctmGetFloatArray() +//----------------------------------------------------------------------------- +CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext, + CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint i; + if(!self) return (CTMfloat *) 0; + + // Did the user request a UV map? + if((aProperty >= CTM_UV_MAP_1) && + ((CTMuint)(aProperty - CTM_UV_MAP_1) < self->mUVMapCount)) + { + map = self->mUVMaps; + i = CTM_UV_MAP_1; + while(map && (i != aProperty)) + { + map = map->mNext; + ++ i; + } + if(!map) + { + self->mError = CTM_INTERNAL_ERROR; + return (CTMfloat *) 0; + } + return map->mValues; + } + + // Did the user request an attribute map? + if((aProperty >= CTM_ATTRIB_MAP_1) && + ((CTMuint)(aProperty - CTM_ATTRIB_MAP_1) < self->mAttribMapCount)) + { + map = self->mAttribMaps; + i = CTM_ATTRIB_MAP_1; + while(map && (i != aProperty)) + { + map = map->mNext; + ++ i; + } + if(!map) + { + self->mError = CTM_INTERNAL_ERROR; + return (CTMfloat *) 0; + } + return map->mValues; + } + + switch(aProperty) + { + case CTM_VERTICES: + return self->mVertices; + + case CTM_NORMALS: + return self->mNormals; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return (CTMfloat *) 0; +} + +//----------------------------------------------------------------------------- +// ctmGetNamedUVMap() +//----------------------------------------------------------------------------- +CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext, + const char * aName) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint result; + if(!self) return CTM_NONE; + + map = self->mUVMaps; + result = CTM_UV_MAP_1; + while(map && (strcmp(aName, map->mName) != 0)) + { + map = map->mNext; + ++ result; + } + if(!map) + { + return CTM_NONE; + } + return result; +} + +//----------------------------------------------------------------------------- +// ctmGetUVMapString() +//----------------------------------------------------------------------------- +CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext, + CTMenum aUVMap, CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint i; + if(!self) return (const char *) 0; + + // Find the indicated map + map = self->mUVMaps; + i = CTM_UV_MAP_1; + while(map && (i != aUVMap)) + { + ++ i; + map = map->mNext; + } + if(!map) + { + self->mError = CTM_INVALID_ARGUMENT; + return (const char *) 0; + } + + // Get the requested string + switch(aProperty) + { + case CTM_NAME: + return (const char *) map->mName; + + case CTM_FILE_NAME: + return (const char *) map->mFileName; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return (const char *) 0; +} + +//----------------------------------------------------------------------------- +// ctmGetUVMapFloat() +//----------------------------------------------------------------------------- +CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext, + CTMenum aUVMap, CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint i; + if(!self) return 0.0f; + + // Find the indicated map + map = self->mUVMaps; + i = CTM_UV_MAP_1; + while(map && (i != aUVMap)) + { + ++ i; + map = map->mNext; + } + if(!map) + { + self->mError = CTM_INVALID_ARGUMENT; + return 0.0f; + } + + // Get the requested string + switch(aProperty) + { + case CTM_PRECISION: + return map->mPrecision; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return 0.0f; +} + +//----------------------------------------------------------------------------- +// ctmGetAttribMapString() +//----------------------------------------------------------------------------- +CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext, + CTMenum aAttribMap, CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint i; + if(!self) return (const char *) 0; + + // Find the indicated map + map = self->mAttribMaps; + i = CTM_ATTRIB_MAP_1; + while(map && (i != aAttribMap)) + { + ++ i; + map = map->mNext; + } + if(!map) + { + self->mError = CTM_INVALID_ARGUMENT; + return (const char *) 0; + } + + // Get the requested string + switch(aProperty) + { + case CTM_NAME: + return (const char *) map->mName; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return (const char *) 0; +} + +//----------------------------------------------------------------------------- +// ctmGetAttribMapFloat() +//----------------------------------------------------------------------------- +CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext, + CTMenum aAttribMap, CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint i; + if(!self) return 0.0f; + + // Find the indicated map + map = self->mAttribMaps; + i = CTM_ATTRIB_MAP_1; + while(map && (i != aAttribMap)) + { + ++ i; + map = map->mNext; + } + if(!map) + { + self->mError = CTM_INVALID_ARGUMENT; + return 0.0f; + } + + // Get the requested string + switch(aProperty) + { + case CTM_PRECISION: + return map->mPrecision; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return 0.0f; +} + +//----------------------------------------------------------------------------- +// ctmGetNamedAttribMap() +//----------------------------------------------------------------------------- +CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext, + const char * aName) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint result; + if(!self) return CTM_NONE; + + map = self->mAttribMaps; + result = CTM_ATTRIB_MAP_1; + while(map && (strcmp(aName, map->mName) != 0)) + { + map = map->mNext; + ++ result; + } + if(!map) + { + return CTM_NONE; + } + return result; +} + +//----------------------------------------------------------------------------- +// ctmGetString() +//----------------------------------------------------------------------------- +CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext, + CTMenum aProperty) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return 0; + + switch(aProperty) + { + case CTM_FILE_COMMENT: + return (const char *) self->mFileComment; + + default: + self->mError = CTM_INVALID_ARGUMENT; + } + + return (const char *) 0; +} + +//----------------------------------------------------------------------------- +// ctmCompressionMethod() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext, + CTMenum aMethod) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return; + + // You are only allowed to change compression attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if((aMethod != CTM_METHOD_RAW) && (aMethod != CTM_METHOD_MG1) && + (aMethod != CTM_METHOD_MG2)) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Set method + self->mMethod = aMethod; +} + +//----------------------------------------------------------------------------- +// ctmCompressionLevel() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext, + CTMuint aLevel) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return; + + // You are only allowed to change compression attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if(aLevel > 9) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Set the compression level + self->mCompressionLevel = aLevel; +} + +//----------------------------------------------------------------------------- +// ctmVertexPrecision() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext, + CTMfloat aPrecision) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return; + + // You are only allowed to change compression attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if(aPrecision <= 0.0f) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Set precision + self->mVertexPrecision = aPrecision; +} + +//----------------------------------------------------------------------------- +// ctmVertexPrecisionRel() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext, + CTMfloat aRelPrecision) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + CTMfloat avgEdgeLength, * p1, * p2; + CTMuint edgeCount, i, j; + if(!self) return; + + // You are only allowed to change compression attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if(aRelPrecision <= 0.0f) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Calculate the average edge length (Note: we actually sum up all the half- + // edges, so in a proper solid mesh all connected edges are counted twice) + avgEdgeLength = 0.0f; + edgeCount = 0; + for(i = 0; i < self->mTriangleCount; ++ i) + { + p1 = &self->mVertices[self->mIndices[i * 3 + 2] * 3]; + for(j = 0; j < 3; ++ j) + { + p2 = &self->mVertices[self->mIndices[i * 3 + j] * 3]; + avgEdgeLength += sqrtf((p2[0] - p1[0]) * (p2[0] - p1[0]) + + (p2[1] - p1[1]) * (p2[1] - p1[1]) + + (p2[2] - p1[2]) * (p2[2] - p1[2])); + p1 = p2; + ++ edgeCount; + } + } + if(edgeCount == 0) + { + self->mError = CTM_INVALID_MESH; + return; + } + avgEdgeLength /= (CTMfloat) edgeCount; + + // Set precision + self->mVertexPrecision = aRelPrecision * avgEdgeLength; +} + +//----------------------------------------------------------------------------- +// ctmNormalPrecision() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext, + CTMfloat aPrecision) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return; + + // You are only allowed to change compression attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if(aPrecision <= 0.0f) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Set precision + self->mNormalPrecision = aPrecision; +} + +//----------------------------------------------------------------------------- +// ctmUVCoordPrecision() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext, + CTMenum aUVMap, CTMfloat aPrecision) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint i; + if(!self) return; + + // You are only allowed to change compression attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if(aPrecision <= 0.0f) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Find the indicated map + map = self->mUVMaps; + i = CTM_UV_MAP_1; + while(map && (i != aUVMap)) + { + ++ i; + map = map->mNext; + } + if(!map) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Update the precision + map->mPrecision = aPrecision; +} + +//----------------------------------------------------------------------------- +// ctmAttribPrecision() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext, + CTMenum aAttribMap, CTMfloat aPrecision) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + CTMuint i; + if(!self) return; + + // You are only allowed to change compression attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if(aPrecision <= 0.0f) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Find the indicated map + map = self->mAttribMaps; + i = CTM_ATTRIB_MAP_1; + while(map && (i != aAttribMap)) + { + ++ i; + map = map->mNext; + } + if(!map) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Update the precision + map->mPrecision = aPrecision; +} + +//----------------------------------------------------------------------------- +// ctmFileComment() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext, + const char * aFileComment) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + int len; + if(!self) return; + + // You are only allowed to change file attributes in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Free the old comment string, if necessary + if(self->mFileComment) + { + free(self->mFileComment); + self->mFileComment = (char *) 0; + } + + // Get length of string (if empty, do nothing) + if(!aFileComment) + return; + len = strlen(aFileComment); + if(!len) + return; + + // Copy the string + self->mFileComment = (char *) malloc(len + 1); + if(!self->mFileComment) + { + self->mError = CTM_OUT_OF_MEMORY; + return; + } + strcpy(self->mFileComment, aFileComment); +} + +//----------------------------------------------------------------------------- +// ctmDefineMesh() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext, + const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices, + CTMuint aTriangleCount, const CTMfloat * aNormals) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + if(!self) return; + + // You are only allowed to (re)define the mesh in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check arguments + if(!aVertices || !aIndices || !aVertexCount || !aTriangleCount) + { + self->mError = CTM_INVALID_ARGUMENT; + return; + } + + // Clear the old mesh, if any + _ctmClearMesh(self); + + // Set vertex array pointer + self->mVertices = (CTMfloat *) aVertices; + self->mVertexCount = aVertexCount; + + // Set index array pointer + self->mIndices = (CTMuint *) aIndices; + self->mTriangleCount = aTriangleCount; + + // Set normal array pointer + self->mNormals = (CTMfloat *) aNormals; +} + +//----------------------------------------------------------------------------- +// _ctmAddFloatMap() +//----------------------------------------------------------------------------- +static _CTMfloatmap * _ctmAddFloatMap(_CTMcontext * self, + const CTMfloat * aValues, const char * aName, const char * aFileName, + _CTMfloatmap ** aList) +{ + _CTMfloatmap * map; + CTMuint len; + + // Allocate memory for a new map list item and append it to the list + if(!*aList) + { + *aList = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); + map = *aList; + } + else + { + map = *aList; + while(map->mNext) + map = map->mNext; + map->mNext = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); + map = map->mNext; + } + if(!map) + { + self->mError = CTM_OUT_OF_MEMORY; + return (_CTMfloatmap *) 0; + } + + // Init the map item + memset(map, 0, sizeof(_CTMfloatmap)); + map->mPrecision = 1.0f / 1024.0f; + map->mValues = (CTMfloat *) aValues; + + // Set name of the map + if(aName) + { + // Get length of string (if empty, do nothing) + len = strlen(aName); + if(len) + { + // Copy the string + map->mName = (char *) malloc(len + 1); + if(!map->mName) + { + self->mError = CTM_OUT_OF_MEMORY; + free(map); + return (_CTMfloatmap *) 0; + } + strcpy(map->mName, aName); + } + } + + // Set file name reference for the map + if(aFileName) + { + // Get length of string (if empty, do nothing) + len = strlen(aFileName); + if(len) + { + // Copy the string + map->mFileName = (char *) malloc(len + 1); + if(!map->mFileName) + { + self->mError = CTM_OUT_OF_MEMORY; + if(map->mName) + free(map->mName); + free(map); + return (_CTMfloatmap *) 0; + } + strcpy(map->mFileName, aFileName); + } + } + + return map; +} + +//----------------------------------------------------------------------------- +// ctmAddUVMap() +//----------------------------------------------------------------------------- +CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext, + const CTMfloat * aUVCoords, const char * aName, const char * aFileName) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + if(!self) return CTM_NONE; + + // Add a new UV map to the UV map list + map = _ctmAddFloatMap(self, aUVCoords, aName, aFileName, &self->mUVMaps); + if(!map) + return CTM_NONE; + else + { + // The default UV coordinate precision is 2^-12 + map->mPrecision = 1.0f / 4096.0f; + ++ self->mUVMapCount; + return CTM_UV_MAP_1 + self->mUVMapCount - 1; + } +} + +//----------------------------------------------------------------------------- +// ctmAddAttribMap() +//----------------------------------------------------------------------------- +CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext, + const CTMfloat * aAttribValues, const char * aName) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + _CTMfloatmap * map; + if(!self) return CTM_NONE; + + // Add a new attribute map to the attribute map list + map = _ctmAddFloatMap(self, aAttribValues, aName, (const char *) 0, + &self->mAttribMaps); + if(!map) + return CTM_NONE; + else + { + // The default vertex attribute precision is 2^-8 + map->mPrecision = 1.0f / 256.0f; + ++ self->mAttribMapCount; + return CTM_ATTRIB_MAP_1 + self->mAttribMapCount - 1; + } +} + +//----------------------------------------------------------------------------- +// _ctmDefaultRead() +//----------------------------------------------------------------------------- +static CTMuint CTMCALL _ctmDefaultRead(void * aBuf, CTMuint aCount, + void * aUserData) +{ + return (CTMuint) fread(aBuf, 1, (size_t) aCount, (FILE *) aUserData); +} + +//----------------------------------------------------------------------------- +// ctmLoad() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + FILE * f; + if(!self) return; + + // You are only allowed to load data in import mode + if(self->mMode != CTM_IMPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Open file stream + f = fopen(aFileName, "rb"); + if(!f) + { + self->mError = CTM_FILE_ERROR; + return; + } + + // Load the file + ctmLoadCustom(self, _ctmDefaultRead, (void *) f); + + // Close file stream + fclose(f); +} + +//----------------------------------------------------------------------------- +// _ctmAllocateFloatMaps() +//----------------------------------------------------------------------------- +static CTMuint _ctmAllocateFloatMaps(_CTMcontext * self, + _CTMfloatmap ** aMapListPtr, CTMuint aCount, CTMuint aChannels) +{ + _CTMfloatmap ** mapListPtr; + CTMuint i, size; + + mapListPtr = aMapListPtr; + for(i = 0; i < aCount; ++ i) + { + // Allocate & clear memory for this map + *mapListPtr = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); + if(!*mapListPtr) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + memset(*mapListPtr, 0, sizeof(_CTMfloatmap)); + + // Allocate & clear memory for the float array + size = aChannels * sizeof(CTMfloat) * self->mVertexCount; + (*mapListPtr)->mValues = (CTMfloat *) malloc(size); + if(!(*mapListPtr)->mValues) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + memset((*mapListPtr)->mValues, 0, size); + + // Next map... + mapListPtr = &(*mapListPtr)->mNext; + } + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// ctmLoadCustom() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, + void * aUserData) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + CTMuint formatVersion, flags, method; + if(!self) return; + + // You are only allowed to load data in import mode + if(self->mMode != CTM_IMPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Initialize stream + self->mReadFn = aReadFn; + self->mUserData = aUserData; + + // Clear any old mesh arrays + _ctmClearMesh(self); + + // Read header from stream + if(_ctmStreamReadUINT(self) != FOURCC("OCTM")) + { + self->mError = CTM_BAD_FORMAT; + return; + } + formatVersion = _ctmStreamReadUINT(self); + if(formatVersion != _CTM_FORMAT_VERSION) + { + self->mError = CTM_UNSUPPORTED_FORMAT_VERSION; + return; + } + method = _ctmStreamReadUINT(self); + if(method == FOURCC("RAW\0")) + self->mMethod = CTM_METHOD_RAW; + else if(method == FOURCC("MG1\0")) + self->mMethod = CTM_METHOD_MG1; + else if(method == FOURCC("MG2\0")) + self->mMethod = CTM_METHOD_MG2; + else + { + self->mError = CTM_BAD_FORMAT; + return; + } + self->mVertexCount = _ctmStreamReadUINT(self); + if(self->mVertexCount == 0) + { + self->mError = CTM_BAD_FORMAT; + return; + } + self->mTriangleCount = _ctmStreamReadUINT(self); + if(self->mTriangleCount == 0) + { + self->mError = CTM_BAD_FORMAT; + return; + } + self->mUVMapCount = _ctmStreamReadUINT(self); + self->mAttribMapCount = _ctmStreamReadUINT(self); + flags = _ctmStreamReadUINT(self); + _ctmStreamReadSTRING(self, &self->mFileComment); + + // Allocate memory for the mesh arrays + self->mVertices = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3); + if(!self->mVertices) + { + self->mError = CTM_OUT_OF_MEMORY; + return; + } + self->mIndices = (CTMuint *) malloc(self->mTriangleCount * sizeof(CTMuint) * 3); + if(!self->mIndices) + { + _ctmClearMesh(self); + self->mError = CTM_OUT_OF_MEMORY; + return; + } + if(flags & _CTM_HAS_NORMALS_BIT) + { + self->mNormals = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3); + if(!self->mNormals) + { + _ctmClearMesh(self); + self->mError = CTM_OUT_OF_MEMORY; + return; + } + } + + // Allocate memory for the UV and attribute maps (if any) + if(!_ctmAllocateFloatMaps(self, &self->mUVMaps, self->mUVMapCount, 2)) + { + _ctmClearMesh(self); + self->mError = CTM_OUT_OF_MEMORY; + return; + } + if(!_ctmAllocateFloatMaps(self, &self->mAttribMaps, self->mAttribMapCount, 4)) + { + _ctmClearMesh(self); + self->mError = CTM_OUT_OF_MEMORY; + return; + } + + // Uncompress from stream + switch(self->mMethod) + { + case CTM_METHOD_RAW: + _ctmUncompressMesh_RAW(self); + break; + + case CTM_METHOD_MG1: + _ctmUncompressMesh_MG1(self); + break; + + case CTM_METHOD_MG2: + _ctmUncompressMesh_MG2(self); + break; + + default: + self->mError = CTM_INTERNAL_ERROR; + } + + // Check mesh integrity + if(!_ctmCheckMeshIntegrity(self)) + { + self->mError = CTM_INVALID_MESH; + return; + } +} + +//----------------------------------------------------------------------------- +// _ctmDefaultWrite() +//----------------------------------------------------------------------------- +static CTMuint CTMCALL _ctmDefaultWrite(const void * aBuf, CTMuint aCount, + void * aUserData) +{ + return (CTMuint) fwrite(aBuf, 1, (size_t) aCount, (FILE *) aUserData); +} + +//----------------------------------------------------------------------------- +// ctmSave() +//----------------------------------------------------------------------------- +CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + FILE * f; + if(!self) return; + + // You are only allowed to save data in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Open file stream + f = fopen(aFileName, "wb"); + if(!f) + { + self->mError = CTM_FILE_ERROR; + return; + } + + // Save the file + ctmSaveCustom(self, _ctmDefaultWrite, (void *) f); + + // Close file stream + fclose(f); +} + +//----------------------------------------------------------------------------- +// ctmSaveCustom() +//----------------------------------------------------------------------------- +void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, + void * aUserData) +{ + _CTMcontext * self = (_CTMcontext *) aContext; + CTMuint flags; + if(!self) return; + + // You are only allowed to save data in export mode + if(self->mMode != CTM_EXPORT) + { + self->mError = CTM_INVALID_OPERATION; + return; + } + + // Check mesh integrity + if(!_ctmCheckMeshIntegrity(self)) + { + self->mError = CTM_INVALID_MESH; + return; + } + + // Initialize stream + self->mWriteFn = aWriteFn; + self->mUserData = aUserData; + + // Determine flags + flags = 0; + if(self->mNormals) + flags |= _CTM_HAS_NORMALS_BIT; + + // Write header to stream + _ctmStreamWrite(self, (void *) "OCTM", 4); + _ctmStreamWriteUINT(self, _CTM_FORMAT_VERSION); + switch(self->mMethod) + { + case CTM_METHOD_RAW: + _ctmStreamWrite(self, (void *) "RAW\0", 4); + break; + + case CTM_METHOD_MG1: + _ctmStreamWrite(self, (void *) "MG1\0", 4); + break; + + case CTM_METHOD_MG2: + _ctmStreamWrite(self, (void *) "MG2\0", 4); + break; + + default: + self->mError = CTM_INTERNAL_ERROR; + return; + } + _ctmStreamWriteUINT(self, self->mVertexCount); + _ctmStreamWriteUINT(self, self->mTriangleCount); + _ctmStreamWriteUINT(self, self->mUVMapCount); + _ctmStreamWriteUINT(self, self->mAttribMapCount); + _ctmStreamWriteUINT(self, flags); + _ctmStreamWriteSTRING(self, self->mFileComment); + + // Compress to stream + switch(self->mMethod) + { + case CTM_METHOD_RAW: + _ctmCompressMesh_RAW(self); + break; + + case CTM_METHOD_MG1: + _ctmCompressMesh_MG1(self); + break; + + case CTM_METHOD_MG2: + _ctmCompressMesh_MG2(self); + break; + + default: + self->mError = CTM_INTERNAL_ERROR; + return; + } +} diff --git a/src/external/OpenCTM-1.0.3/lib/openctm.h b/src/external/OpenCTM-1.0.3/lib/openctm.h new file mode 100644 index 000000000..c395f93e6 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/openctm.h @@ -0,0 +1,655 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: openctm.h +// Description: OpenCTM API definition. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +#ifndef __OPENCTM_H_ +#define __OPENCTM_H_ + +/*! @mainpage OpenCTM API Reference + * + * @section intro_sec Introduction + * + * OpenCTM is an open file format for storing compressed triangle meshes. + * In order to easily read and write OpenCTM files (usually suffixed .ctm) an + * API (Application Program Interface) is provided that can easily be used from + * most modern programming languages. + * + * The OpenCTM functionality itself is written in highly portable standard C + * (C99). + * + * @section usage_sec Usage + * + * For information about how to use the OpenCTM API, see openctm.h. + * + * For information about the C++ wrapper classes, see CTMimporter and + * CTMexporter. + * + * @section example_sec Example usage + * + * @subsection example_load_sec Loading a CTM file + * + * Here is a simple example of loading a CTM file: + * + * @code + * CTMcontext context; + * CTMuint vertCount, triCount, * indices; + * CTMfloat * vertices; + * + * // Create a new context + * context = ctmNewContext(CTM_IMPORT); + * + * // Load the OpenCTM file + * ctmLoad(context, "mymesh.ctm"); + * if(ctmGetError(context) == CTM_NONE) + * { + * // Access the mesh data + * vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT); + * vertices = ctmGetFloatArray(context, CTM_VERTICES); + * triCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT); + * indices = ctmGetIntegerArray(context, CTM_INDICES); + * + * // Deal with the mesh (e.g. transcode it to our internal representation) + * // ... + * } + * + * // Free the context + * ctmFreeContext(context); + * @endcode + * + * @subsection example_create_sec Creating a CTM file + * + * Here is a simple example of creating a CTM file: + * + * @code + * CTMcontext context; + * CTMuint vertCount, triCount, * indices; + * CTMfloat * vertices; + * + * // Create our mesh in memory + * vertCount = 100; + * triCount = 120; + * vertices = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * vertCount); + * indices = (CTMuint *) malloc(3 * sizeof(CTMuint) * triCount); + * // ... + * + * // Create a new context + * context = ctmNewContext(CTM_EXPORT); + * + * // Define our mesh representation to OpenCTM (store references to it in + * // the context) + * ctmDefineMesh(context, vertices, vertCount, indices, triCount, NULL); + * + * // Save the OpenCTM file + * ctmSave(context, "mymesh.ctm"); + * + * // Free the context + * ctmFreeContext(context); + * + * // Free our mesh + * free(indices); + * free(vertices); + * @endcode + */ + +#ifdef __cplusplus +extern "C" { +#endif + + +// Declare calling conventions etc. +#if defined(WIN32) || defined(_WIN32) + // Windows + #if defined(OPENCTM_STATIC) + #define CTMEXPORT + #else + #if defined(OPENCTM_BUILD) + #define CTMEXPORT __declspec(dllexport) + #else + #define CTMEXPORT __declspec(dllimport) + #endif + #endif + #if defined(__MINGW32__) + #define CTMCALL __attribute__ ((__stdcall__)) + #elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) + #define CTMCALL __stdcall + #else + #define CTMCALL + #endif +#else + // Unix + #if !defined(OPENCTM_STATIC) && !defined(OPENCTM_BUILD) + #define CTMEXPORT extern + #else + #if defined(OPENCTM_BUILD) && defined(__GNUC__) && (__GNUC__ >= 4) + #define CTMEXPORT __attribute__ ((visibility("default"))) + #else + #define CTMEXPORT + #endif + #endif + #define CTMCALL +#endif + + +// Get system specific type definitions for sized integers. We use the C99 +// standard stdint.h for this. +#ifdef _MSC_VER + // MS Visual Studio does not support C99 + typedef int int32_t; + typedef unsigned int uint32_t; +#else + #include +#endif + + +/// OpenCTM API version (1.0). +#define CTM_API_VERSION 0x00000100 + +/// Boolean TRUE. +#define CTM_TRUE 1 + +/// Boolean FALSE. +#define CTM_FALSE 0 + +/// Single precision floating point type (IEEE 754 32 bits wide). +typedef float CTMfloat; + +/// Signed integer (32 bits wide). +typedef int32_t CTMint; + +/// Unsigned integer (32 bits wide). +typedef uint32_t CTMuint; + +/// OpenCTM context handle. +typedef void * CTMcontext; + +/// OpenCTM specific enumerators. +/// @note For the information query functions, it is an error to query a value +/// of the wrong type (e.g. to query a string value with the +/// ctmGetInteger() function). +typedef enum { + // Error codes (see ctmGetError()) + CTM_NONE = 0x0000, ///< No error has occured (everything is OK). + /// Also used as an error return value for + /// functions that should return a CTMenum + /// value. + CTM_INVALID_CONTEXT = 0x0001, ///< The OpenCTM context was invalid (e.g. NULL). + CTM_INVALID_ARGUMENT = 0x0002, ///< A function argument was invalid. + CTM_INVALID_OPERATION = 0x0003, ///< The operation is not allowed. + CTM_INVALID_MESH = 0x0004, ///< The mesh was invalid (e.g. no vertices). + CTM_OUT_OF_MEMORY = 0x0005, ///< Not enough memory to proceed. + CTM_FILE_ERROR = 0x0006, ///< File I/O error. + CTM_BAD_FORMAT = 0x0007, ///< File format error (e.g. unrecognized format or corrupted file). + CTM_LZMA_ERROR = 0x0008, ///< An error occured within the LZMA library. + CTM_INTERNAL_ERROR = 0x0009, ///< An internal error occured (indicates a bug). + CTM_UNSUPPORTED_FORMAT_VERSION = 0x000A, ///< Unsupported file format version. + + // OpenCTM context modes + CTM_IMPORT = 0x0101, ///< The OpenCTM context will be used for importing data. + CTM_EXPORT = 0x0102, ///< The OpenCTM context will be used for exporting data. + + // Compression methods + CTM_METHOD_RAW = 0x0201, ///< Just store the raw data. + CTM_METHOD_MG1 = 0x0202, ///< Lossless compression (floating point). + CTM_METHOD_MG2 = 0x0203, ///< Lossless compression (fixed point). + + // Context queries + CTM_VERTEX_COUNT = 0x0301, ///< Number of vertices in the mesh (integer). + CTM_TRIANGLE_COUNT = 0x0302, ///< Number of triangles in the mesh (integer). + CTM_HAS_NORMALS = 0x0303, ///< CTM_TRUE if the mesh has normals (integer). + CTM_UV_MAP_COUNT = 0x0304, ///< Number of UV coordinate sets (integer). + CTM_ATTRIB_MAP_COUNT = 0x0305, ///< Number of custom attribute sets (integer). + CTM_VERTEX_PRECISION = 0x0306, ///< Vertex precision - for MG2 (float). + CTM_NORMAL_PRECISION = 0x0307, ///< Normal precision - for MG2 (float). + CTM_COMPRESSION_METHOD = 0x0308, ///< Compression method (integer). + CTM_FILE_COMMENT = 0x0309, ///< File comment (string). + + // UV/attribute map queries + CTM_NAME = 0x0501, ///< Unique name (UV/attrib map string). + CTM_FILE_NAME = 0x0502, ///< File name reference (UV map string). + CTM_PRECISION = 0x0503, ///< Value precision (UV/attrib map float). + + // Array queries + CTM_INDICES = 0x0601, ///< Triangle indices (integer array). + CTM_VERTICES = 0x0602, ///< Vertex point coordinates (float array). + CTM_NORMALS = 0x0603, ///< Per vertex normals (float array). + CTM_UV_MAP_1 = 0x0700, ///< Per vertex UV map 1 (float array). + CTM_UV_MAP_2 = 0x0701, ///< Per vertex UV map 2 (float array). + CTM_UV_MAP_3 = 0x0702, ///< Per vertex UV map 3 (float array). + CTM_UV_MAP_4 = 0x0703, ///< Per vertex UV map 4 (float array). + CTM_UV_MAP_5 = 0x0704, ///< Per vertex UV map 5 (float array). + CTM_UV_MAP_6 = 0x0705, ///< Per vertex UV map 6 (float array). + CTM_UV_MAP_7 = 0x0706, ///< Per vertex UV map 7 (float array). + CTM_UV_MAP_8 = 0x0707, ///< Per vertex UV map 8 (float array). + CTM_ATTRIB_MAP_1 = 0x0800, ///< Per vertex attribute map 1 (float array). + CTM_ATTRIB_MAP_2 = 0x0801, ///< Per vertex attribute map 2 (float array). + CTM_ATTRIB_MAP_3 = 0x0802, ///< Per vertex attribute map 3 (float array). + CTM_ATTRIB_MAP_4 = 0x0803, ///< Per vertex attribute map 4 (float array). + CTM_ATTRIB_MAP_5 = 0x0804, ///< Per vertex attribute map 5 (float array). + CTM_ATTRIB_MAP_6 = 0x0805, ///< Per vertex attribute map 6 (float array). + CTM_ATTRIB_MAP_7 = 0x0806, ///< Per vertex attribute map 7 (float array). + CTM_ATTRIB_MAP_8 = 0x0807 ///< Per vertex attribute map 8 (float array). +} CTMenum; + +/// Stream read() function pointer. +/// @param[in] aBuf Pointer to the memory buffer to which data should be read. +/// @param[in] aCount The number of bytes to read. +/// @param[in] aUserData The custom user data that was passed to the +/// ctmLoadCustom() function. +/// @return The number of bytes actually read (if this is less than aCount, it +/// indicates that an error occured or the end of file was reached +/// before all bytes were read). +typedef CTMuint (CTMCALL * CTMreadfn)(void * aBuf, CTMuint aCount, void * aUserData); + +/// Stream write() function pointer. +/// @param[in] aBuf Pointer to the memory buffer from which data should be written. +/// @param[in] aCount The number of bytes to write. +/// @param[in] aUserData The custom user data that was passed to the +/// ctmSaveCustom() function. +/// @return The number of bytes actually written (if this is less than aCount, it +/// indicates that an error occured). +typedef CTMuint (CTMCALL * CTMwritefn)(const void * aBuf, CTMuint aCount, void * aUserData); + +/// Create a new OpenCTM context. The context is used for all subsequent +/// OpenCTM function calls. Several contexts can coexist at the same time. +/// @param[in] aMode An OpenCTM context mode. Set this to CTM_IMPORT if the +/// context will be used for importing data, or set it to CTM_EXPORT +/// if it will be used for exporting data. +/// @return An OpenCTM context handle (or NULL if no context could be created). +CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode); + +/// Free an OpenCTM context. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @see ctmNewContext() +CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext); + +/// Returns the latest error. Calling this function will return the last +/// produced error code, or CTM_NO_ERROR (zero) if no error has occured since +/// the last call to ctmGetError(). When this function is called, the internal +/// error varibale will be reset to CTM_NONE. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @return An OpenCTM error code. +/// @see CTMenum +CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext); + +/// Converts an OpenCTM error code to a zero-terminated string. +/// @param[in] aError An OpenCTM error code, as returned by ctmGetError(). +/// @return A zero terminated string that describes the error. For instance, +/// if \c aError is CTM_INVALID_OPERATION, then the return value will +/// be "CTM_INVALID_OPERATION". +/// @see CTMenum +CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError); + +/// Get information about an OpenCTM context. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aProperty Which property to return. +/// @return An integer value, representing the OpenCTM context property given +/// by \c aProperty. +/// @see CTMenum +CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty); + +/// Get information about an OpenCTM context. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aProperty Which property to return. +/// @return A floating point value, representing the OpenCTM context property +/// given by \c aProperty. +/// @see CTMenum +CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty); + +/// Get an integer array from an OpenCTM context. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aProperty Which array to return. +/// @return An integer array. If the requested array does not exist, or +/// if \c aProperty does not indicate an integer array, the function +/// returns NULL. +/// @note The array is only valid as long as the OpenCTM context is valid, or +/// until the corresponding array changes within the OpenCTM context. +/// Trying to access an invalid array will result in undefined +/// behaviour. Therefor it is recommended that the array is copied to +/// a new variable if it is to be used other than directly after the call +/// to ctmGetIntegerArray(). +/// @see CTMenum +CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext, + CTMenum aProperty); + +/// Get a floating point array from an OpenCTM context. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aProperty Which array to return. +/// @return A floating point array. If the requested array does not exist, or +/// if \c aProperty does not indicate a float array, the function +/// returns NULL. +/// @note The array is only valid as long as the OpenCTM context is valid, or +/// until the corresponding array changes within the OpenCTM context. +/// Trying to access an invalid array will result in undefined +/// behaviour. Therefor it is recommended that the array is copied to +/// a new variable if it is to be used other than directly after the call +/// to ctmGetFloatArray(). +/// @see CTMenum +CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext, + CTMenum aProperty); + +/// Get a reference to the named UV map. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aName The name of the UV map that should be returned. +/// @return A reference to a UV map. If the UV map was found, a value of +/// CTM_UV_MAP_1 or higher is returned, otherwise CTM_NONE is +/// returned. +CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext, + const char * aName); + +/// Get information about a UV map. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher). +/// @param[in] aProperty Which UV map property to return. +/// @return A string value, representing the UV map property given +/// by \c aProperty. +/// @note The string is only valid as long as the UV map within the OpenCTM +/// context is valid. Trying to access an invalid string will result in +/// undefined behaviour. Therefor it is recommended that the string is +/// copied to a new variable if it is to be used other than directly after +/// the call to ctmGetUVMapString(). +/// @see CTMenum +CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext, + CTMenum aUVMap, CTMenum aProperty); + +/// Get information about a UV map. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher). +/// @param[in] aProperty Which UV map property to return. +/// @return A floating point value, representing the UV map property given +/// by \c aProperty. +/// @see CTMenum +CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext, + CTMenum aUVMap, CTMenum aProperty); + +/// Get a reference to the named vertex attribute map. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aName The name of the attribute map that should be returned. +/// @return A reference to an attribute map. If the attribute map was found, +/// a value of CTM_ATTRIB_MAP_1 or higher is returned, otherwise +/// CTM_NONE is returned. +CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext, + const char * aName); + +/// Get information about a vertex attribute map. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 +/// or higher). +/// @param[in] aProperty Which vertex attribute map property to return. +/// @return A string value, representing the vertex attribute map property given +/// by \c aProperty. +/// @note The string is only valid as long as the vertex attribute map within +/// the OpenCTM context is valid. Trying to access an invalid string will +/// result in undefined behaviour. Therefor it is recommended that the +/// string is copied to a new variable if it is to be used other than +/// directly after the call to ctmGetAttribMapString(). +/// @see CTMenum +CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext, + CTMenum aAttribMap, CTMenum aProperty); + +/// Get information about a vertex attribute map. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 +/// or higher). +/// @param[in] aProperty Which vertex attribute map property to return. +/// @return A floating point value, representing the vertex attribute map +/// property given by \c aProperty. +/// @see CTMenum +CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext, + CTMenum aAttribMap, CTMenum aProperty); + +/// Get information about an OpenCTM context. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aProperty Which property to return. +/// @return A string value, representing the OpenCTM context property given +/// by \c aProperty. +/// @note The string is only valid as long as the OpenCTM context is valid, or +/// until the corresponding string changes within the OpenCTM context +/// (e.g. calling ctmFileComment() invalidates the CTM_FILE_COMMENT +/// string). Trying to access an invalid string will result in undefined +/// behaviour. Therefor it is recommended that the string is copied to +/// a new variable if it is to be used other than directly after the call +/// to ctmGetString(). +/// @see CTMenum +CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext, + CTMenum aProperty); + +/// Set which compression method to use for the given OpenCTM context. +/// The selected compression method will be used when calling the ctmSave() +/// function. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aMethod Which compression method to use: CTM_METHOD_RAW, +/// CTM_METHOD_MG1 or CTM_METHOD_MG2 (the default method is +/// CTM_METHOD_MG1). +/// @see CTM_METHOD_RAW, CTM_METHOD_MG1, CTM_METHOD_MG2 +CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext, + CTMenum aMethod); + +/// Set which LZMA compression level to use for the given OpenCTM context. +/// The compression level can be between 0 (fastest) and 9 (best). The higher +/// the compression level, the more memory is required for compression and +/// decompression. The default compression level is 1. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aLevel Which compression level to use (0 to 9). +CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext, + CTMuint aLevel); + +/// Set the vertex coordinate precision (only used by the MG2 compression +/// method). +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aPrecision Fixed point precision. For instance, if this value is +/// 0.001, all vertex coordinates will be rounded to three decimals. +/// The default vertex coordinate precision is 2^-10 ~= 0.00098. +CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext, + CTMfloat aPrecision); + +/// Set the vertex coordinate precision, relative to the mesh dimensions (only +/// used by the MG2 compression method). +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aRelPrecision Relative precision. This factor is multiplied by the +/// average triangle edge length in the mesh in order to obtain the +/// final, fixed point precision. For instance, if aRelPrecision is +/// 0.01, and the average edge length is 3.7, then the fixed point +/// precision is set to 0.037. +/// @note The mesh must have been defined using the ctmDefineMesh() function +/// before calling this function. +/// @see ctmVertexPrecision(). +CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext, + CTMfloat aRelPrecision); + +/// Set the normal precision (only used by the MG2 compression method). The +/// normal is represented in spherical coordinates in the MG2 compression +/// method, and the normal precision controls the angular and radial resolution. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aPrecision Fixed point precision. For the angular information, +/// this value represents the angular precision. For the radial +/// information, this value is the linear resolution. For instance, +/// 0.01 means that the circle is divided into 100 steps, and the +/// normal magnitude is rounded to 2 decimals. The default normal +/// precision is 2^-8 ~= 0.0039. +CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext, + CTMfloat aPrecision); + +/// Set the coordinate precision for the specified UV map (only used by the +/// MG2 compression method). +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aUVMap A UV map specifier for a defined UV map +/// (CTM_UV_MAP_1, ...). +/// @param[in] aPrecision Fixed point precision. For instance, if this value is +/// 0.001, all UV coordinates will be rounded to three decimals. +/// The default UV coordinate precision is 2^-12 ~= 0.00024. +/// @see ctmAddUVMap(). +CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext, + CTMenum aUVMap, CTMfloat aPrecision); + +/// Set the attribute value precision for the specified attribute map (only +/// used by the MG2 compression method). +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aAttribMap An attribute map specifier for a defined attribute map +/// (CTM_ATTRIB_MAP_1, ...). +/// @param[in] aPrecision Fixed point precision. For instance, if this value is +/// 0.001, all attribute values will be rounded to three decimals. +/// If the attributes represent integer values, set the precision +/// to 1.0. The default attribute precision is 2^-8 ~= 0.0039. +/// @see ctmAddAttribMap(). +CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext, + CTMenum aAttribMap, CTMfloat aPrecision); + +/// Set the file comment for the given OpenCTM context. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aFileComment The file comment (zero terminated UTF-8 string). +CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext, + const char * aFileComment); + +/// Define a triangle mesh. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aVertices An array of vertices (three consecutive floats make +/// one vertex). +/// @param[in] aVertexCount The number of vertices in \c aVertices (and +/// optionally \c aTexCoords). +/// @param[in] aIndices An array of vertex indices (three consecutive integers +/// make one triangle). +/// @param[in] aTriangleCount The number of triangles in \c aIndices (there +/// must be exactly 3 x \c aTriangleCount indices in \c aIndices). +/// @param[in] aNormals An array of per-vertex normals (or NULL if there are +/// no normals). Each normal is made up by three consecutive floats, +/// and there must be \c aVertexCount normals. +/// @see ctmAddUVMap(), ctmAddAttribMap(), ctmSave(), ctmSaveCustom(). +CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext, + const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices, + CTMuint aTriangleCount, const CTMfloat * aNormals); + +/// Define a UV map. There can be several UV maps in a mesh. A UV map is +/// typically used for 2D texture mapping. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aUVCoords An array of UV coordinates. Each UV coordinate is made +/// up by two consecutive floats, and there must be as many +/// coordinates as there are vertices in the mesh. +/// @param[in] aName A unique name for this UV map (zero terminated UTF-8 +/// string). +/// @param[in] aFileName A reference to a image file (zero terminated +/// UTF-8 string). If no file name reference exists, pass NULL. +/// @return A UV map index (CTM_UV_MAP_1 and higher). If the function +/// failed, it will return the zero valued CTM_NONE (use ctmGetError() +/// to determine the cause of the error). +/// @note A triangle mesh must have been defined before calling this function, +/// since the number of vertices is defined by the triangle mesh. +/// @see ctmDefineMesh(). +CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext, + const CTMfloat * aUVCoords, const char * aName, const char * aFileName); + +/// Define a custom vertex attribute map. Custom vertex attributes can be used +/// for defining special per-vertex attributes, such as color, weight, ambient +/// occlusion factor, etc. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aAttribValues An array of attribute values. Each attribute value +/// is made up by four consecutive floats, and there must be as many +/// values as there are vertices in the mesh. +/// @param[in] aName A unique name for this attribute map (zero terminated UTF-8 +/// string). +/// @return A attribute map index (CTM_ATTRIB_MAP_1 and higher). If the function +/// failed, it will return the zero valued CTM_NONE (use ctmGetError() +/// to determine the cause of the error). +/// @note A triangle mesh must have been defined before calling this function, +/// since the number of vertices is defined by the triangle mesh. +/// @see ctmDefineMesh(). +CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext, + const CTMfloat * aAttribValues, const char * aName); + +/// Load an OpenCTM format file into the context. The mesh data can be retrieved +/// with the various ctmGet functions. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aFileName The name of the file to be loaded. +CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName); + +/// Load an OpenCTM format file using a custom stream read function. The mesh +/// data can be retrieved with the various ctmGet functions. +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aReadFn Pointer to a custom stream read function. +/// @param[in] aUserData Custom user data, which can be a C language FILE +/// handle, C++ istream object, or a custom object pointer +/// of any type. The user data pointer will be passed to the +/// custom stream read function. +/// @see CTMreadfn. +CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, + void * aUserData); + +/// Save an OpenCTM format file. The mesh must have been defined by +/// ctmDefineMesh(). +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aFileName The name of the file to be saved. +CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName); + +/// Save an OpenCTM format file using a custom stream write function. The mesh +/// must have been defined by ctmDefineMesh(). +/// @param[in] aContext An OpenCTM context that has been created by +/// ctmNewContext(). +/// @param[in] aWriteFn Pointer to a custom stream write function. +/// @param[in] aUserData Custom user data, which can be a C language FILE +/// handle, C++ ostream object, or a custom object pointer +/// of any type. The user data pointer will be passed to the +/// custom stream write function. +/// @see CTMwritefn. +CTMEXPORT void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, + void * aUserData); + +#ifdef __cplusplus +} +#endif + + +// C++ extensions to the API (to disable C++ extensions, define OPENCTM_NO_CPP) +#if defined(__cplusplus) && !defined(OPENCTM_NO_CPP) + #include "openctmpp.h" +#endif + +#endif // __OPENCTM_H_ diff --git a/src/external/OpenCTM-1.0.3/lib/openctm.rc b/src/external/OpenCTM-1.0.3/lib/openctm.rc new file mode 100644 index 000000000..562417e53 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/openctm.rc @@ -0,0 +1,26 @@ + +1 VERSIONINFO + FILEVERSION 1,0,3,0 + PRODUCTVERSION 1,0,3,0 + FILEOS 0x4 + FILETYPE 0x2 + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "ProductVersion", "1.0.3.0" + VALUE "FileVersion", "1.0.3.0" + VALUE "FileDescription", "OpenCTM API shared library" + VALUE "ProductName", "OpenCTM" + VALUE "OriginalFilename", "openctm.dll" + VALUE "LegalCopyright", "© 2009-2010 Marcus Geelnard" + VALUE "License", "This software is released under the zlib/libpng license." + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END + END diff --git a/src/external/OpenCTM-1.0.3/lib/openctmpp.h b/src/external/OpenCTM-1.0.3/lib/openctmpp.h new file mode 100644 index 000000000..e2519f202 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/openctmpp.h @@ -0,0 +1,377 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: openctmpp.h +// Description: C++ wrapper for the OpenCTM API. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +// To disable C++ extensions, define OPENCTM_NO_CPP +#ifndef OPENCTM_NO_CPP + +#ifndef __OPENCTMPP_H_ +#define __OPENCTMPP_H_ + +// Just in case (if this file was included from outside openctm.h)... +#ifndef __OPENCTM_H_ +#include "openctm.h" +#endif + +#include + +/// OpenCTM exception. When an error occurs, a \c ctm_error exception is +/// thrown. Its what() function returns the name of the OpenCTM error code +/// (for instance "CTM_INVALID_OPERATION"). +class ctm_error: public std::exception +{ + private: + CTMenum mErrorCode; + + public: + explicit ctm_error(CTMenum aError) + { + mErrorCode = aError; + } + + virtual const char* what() const throw() + { + return ctmErrorString(mErrorCode); + } + + CTMenum error_code() const throw() + { + return mErrorCode; + } +}; + + +/// OpenCTM importer class. This is a C++ wrapper class for an OpenCTM import +/// context. Usage example: +/// +/// @code +/// // Create a new OpenCTM importer object +/// CTMimporter ctm; +/// +/// // Load the OpenCTM file +/// ctm.Load("mymesh.ctm"); +/// +/// // Access the mesh data +/// vertCount = ctm.GetInteger(CTM_VERTEX_COUNT); +/// vertices = ctm.GetFloatArray(CTM_VERTICES); +/// triCount = ctm.GetInteger(CTM_TRIANGLE_COUNT); +/// indices = ctm.GetIntegerArray(CTM_INDICES); +/// +/// // Deal with the mesh (e.g. transcode it to our internal representation) +/// // ... +/// @endcode + +class CTMimporter { + private: + /// The OpenCTM context handle. + CTMcontext mContext; + + /// Check for OpenCTM errors, and throw an exception if an error has + /// occured. + void CheckError() + { + CTMenum err = ctmGetError(mContext); + if(err != CTM_NONE) + throw ctm_error(err); + } + + public: + /// Constructor + CTMimporter() + { + mContext = ctmNewContext(CTM_IMPORT); + } + + /// Destructor + ~CTMimporter() + { + ctmFreeContext(mContext); + } + + /// Wrapper for ctmGetInteger() + CTMuint GetInteger(CTMenum aProperty) + { + CTMuint res = ctmGetInteger(mContext, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetFloat() + CTMfloat GetFloat(CTMenum aProperty) + { + CTMfloat res = ctmGetFloat(mContext, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetIntegerArray() + const CTMuint * GetIntegerArray(CTMenum aProperty) + { + const CTMuint * res = ctmGetIntegerArray(mContext, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetFloatArray() + const CTMfloat * GetFloatArray(CTMenum aProperty) + { + const CTMfloat * res = ctmGetFloatArray(mContext, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetNamedUVMap() + CTMenum GetNamedUVMap(const char * aName) + { + CTMenum res = ctmGetNamedUVMap(mContext, aName); + CheckError(); + return res; + } + + /// Wrapper for ctmGetUVMapString() + const char * GetUVMapString(CTMenum aUVMap, CTMenum aProperty) + { + const char * res = ctmGetUVMapString(mContext, aUVMap, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetUVMapFloat() + CTMfloat GetUVMapFloat(CTMenum aUVMap, CTMenum aProperty) + { + CTMfloat res = ctmGetUVMapFloat(mContext, aUVMap, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetNamedAttribMap() + CTMenum GetNamedAttribMap(const char * aName) + { + CTMenum res = ctmGetNamedAttribMap(mContext, aName); + CheckError(); + return res; + } + + /// Wrapper for ctmGetAttribMapString() + const char * GetAttribMapString(CTMenum aAttribMap, CTMenum aProperty) + { + const char * res = ctmGetAttribMapString(mContext, aAttribMap, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetAttribMapFloat() + CTMfloat GetAttribMapFloat(CTMenum aAttribMap, CTMenum aProperty) + { + CTMfloat res = ctmGetAttribMapFloat(mContext, aAttribMap, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmGetString() + const char * GetString(CTMenum aProperty) + { + const char * res = ctmGetString(mContext, aProperty); + CheckError(); + return res; + } + + /// Wrapper for ctmLoad() + void Load(const char * aFileName) + { + ctmLoad(mContext, aFileName); + CheckError(); + } + + /// Wrapper for ctmLoadCustom() + void LoadCustom(CTMreadfn aReadFn, void * aUserData) + { + ctmLoadCustom(mContext, aReadFn, aUserData); + CheckError(); + } + + // You can not copy nor assign from one CTMimporter object to another, since + // the object contains hidden state. By declaring these dummy prototypes + // without an implementation, you will at least get linker errors if you try + // to copy or assign a CTMimporter object. + CTMimporter(const CTMimporter& v); + CTMimporter& operator=(const CTMimporter& v); +}; + + +/// OpenCTM exporter class. This is a C++ wrapper class for an OpenCTM export +/// context. Usage example: +/// @code +/// void MySaveFile(CTMuint aVertCount, CTMuint aTriCount, CTMfloat * aVertices, +/// CTMuint * aIndices, const char * aFileName) +/// { +/// // Create a new OpenCTM exporter object +/// CTMexporter ctm; +/// +/// // Define our mesh representation to OpenCTM (store references to it in +/// // the context) +/// ctm.DefineMesh(aVertices, aVertCount, aIndices, aTriCount, NULL); +/// +/// // Save the OpenCTM file +/// ctm.Save(aFileName); +/// } +/// @endcode + +class CTMexporter { + private: + /// The OpenCTM context handle. + CTMcontext mContext; + + /// Check for OpenCTM errors, and throw an exception if an error has + /// occured. + void CheckError() + { + CTMenum err = ctmGetError(mContext); + if(err != CTM_NONE) + throw ctm_error(err); + } + + public: + /// Constructor + CTMexporter() + { + mContext = ctmNewContext(CTM_EXPORT); + } + + /// Destructor + ~CTMexporter() + { + ctmFreeContext(mContext); + } + + /// Wrapper for ctmCompressionMethod() + void CompressionMethod(CTMenum aMethod) + { + ctmCompressionMethod(mContext, aMethod); + CheckError(); + } + + /// Wrapper for ctmCompressionLevel() + void CompressionLevel(CTMuint aLevel) + { + ctmCompressionLevel(mContext, aLevel); + CheckError(); + } + + /// Wrapper for ctmVertexPrecision() + void VertexPrecision(CTMfloat aPrecision) + { + ctmVertexPrecision(mContext, aPrecision); + CheckError(); + } + + /// Wrapper for ctmVertexPrecisionRel() + void VertexPrecisionRel(CTMfloat aRelPrecision) + { + ctmVertexPrecisionRel(mContext, aRelPrecision); + CheckError(); + } + + /// Wrapper for ctmNormalPrecision() + void NormalPrecision(CTMfloat aPrecision) + { + ctmNormalPrecision(mContext, aPrecision); + CheckError(); + } + + /// Wrapper for ctmUVCoordPrecision() + void UVCoordPrecision(CTMenum aUVMap, CTMfloat aPrecision) + { + ctmUVCoordPrecision(mContext, aUVMap, aPrecision); + CheckError(); + } + + /// Wrapper for ctmAttribPrecision() + void AttribPrecision(CTMenum aAttribMap, CTMfloat aPrecision) + { + ctmAttribPrecision(mContext, aAttribMap, aPrecision); + CheckError(); + } + + /// Wrapper for ctmFileComment() + void FileComment(const char * aFileComment) + { + ctmFileComment(mContext, aFileComment); + CheckError(); + } + + /// Wrapper for ctmDefineMesh() + void DefineMesh(const CTMfloat * aVertices, CTMuint aVertexCount, + const CTMuint * aIndices, CTMuint aTriangleCount, + const CTMfloat * aNormals) + { + ctmDefineMesh(mContext, aVertices, aVertexCount, aIndices, aTriangleCount, + aNormals); + CheckError(); + } + + /// Wrapper for ctmAddUVMap() + CTMenum AddUVMap(const CTMfloat * aUVCoords, const char * aName, + const char * aFileName) + { + CTMenum res = ctmAddUVMap(mContext, aUVCoords, aName, aFileName); + CheckError(); + return res; + } + + /// Wrapper for ctmAddAttribMap() + CTMenum AddAttribMap(const CTMfloat * aAttribValues, const char * aName) + { + CTMenum res = ctmAddAttribMap(mContext, aAttribValues, aName); + CheckError(); + return res; + } + + /// Wrapper for ctmSave() + void Save(const char * aFileName) + { + ctmSave(mContext, aFileName); + CheckError(); + } + + /// Wrapper for ctmSaveCustom() + void SaveCustom(CTMwritefn aWriteFn, void * aUserData) + { + ctmSaveCustom(mContext, aWriteFn, aUserData); + CheckError(); + } + + // You can not copy nor assign from one CTMexporter object to another, since + // the object contains hidden state. By declaring these dummy prototypes + // without an implementation, you will at least get linker errors if you try + // to copy or assign a CTMexporter object. + CTMexporter(const CTMexporter& v); + CTMexporter& operator=(const CTMexporter& v); +}; + +#endif // __OPENCTMPP_H_ + +#endif // OPENCTM_NO_CPP diff --git a/src/external/OpenCTM-1.0.3/lib/stream.c b/src/external/OpenCTM-1.0.3/lib/stream.c new file mode 100644 index 000000000..c67f43779 --- /dev/null +++ b/src/external/OpenCTM-1.0.3/lib/stream.c @@ -0,0 +1,512 @@ +//----------------------------------------------------------------------------- +// Product: OpenCTM +// File: stream.c +// Description: Stream I/O functions. +//----------------------------------------------------------------------------- +// Copyright (c) 2009-2010 Marcus Geelnard +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +//----------------------------------------------------------------------------- + +#include +#include +#include +#include "openctm.h" +#include "internal.h" + +#ifdef __DEBUG_ +#include +#endif + +//----------------------------------------------------------------------------- +// _ctmStreamRead() - Read data from a stream. +//----------------------------------------------------------------------------- +CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount) +{ + if(!self->mUserData || !self->mReadFn) + return 0; + + return self->mReadFn(aBuf, aCount, self->mUserData); +} + +//----------------------------------------------------------------------------- +// _ctmStreamWrite() - Write data to a stream. +//----------------------------------------------------------------------------- +CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount) +{ + if(!self->mUserData || !self->mWriteFn) + return 0; + + return self->mWriteFn(aBuf, aCount, self->mUserData); +} + +//----------------------------------------------------------------------------- +// _ctmStreamReadUINT() - Read an unsigned integer from a stream in a machine +// endian independent manner (for portability). +//----------------------------------------------------------------------------- +CTMuint _ctmStreamReadUINT(_CTMcontext * self) +{ + unsigned char buf[4]; + _ctmStreamRead(self, (void *) buf, 4); + return ((CTMuint) buf[0]) | + (((CTMuint) buf[1]) << 8) | + (((CTMuint) buf[2]) << 16) | + (((CTMuint) buf[3]) << 24); +} + +//----------------------------------------------------------------------------- +// _ctmStreamWriteUINT() - Write an unsigned integer to a stream in a machine +// endian independent manner (for portability). +//----------------------------------------------------------------------------- +void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue) +{ + unsigned char buf[4]; + buf[0] = aValue & 0x000000ff; + buf[1] = (aValue >> 8) & 0x000000ff; + buf[2] = (aValue >> 16) & 0x000000ff; + buf[3] = (aValue >> 24) & 0x000000ff; + _ctmStreamWrite(self, (void *) buf, 4); +} + +//----------------------------------------------------------------------------- +// _ctmStreamReadFLOAT() - Read a floating point value from a stream in a +// machine endian independent manner (for portability). +//----------------------------------------------------------------------------- +CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self) +{ + union { + CTMfloat f; + CTMuint i; + } u; + u.i = _ctmStreamReadUINT(self); + return u.f; +} + +//----------------------------------------------------------------------------- +// _ctmStreamWriteFLOAT() - Write a floating point value to a stream in a +// machine endian independent manner (for portability). +//----------------------------------------------------------------------------- +void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue) +{ + union { + CTMfloat f; + CTMuint i; + } u; + u.f = aValue; + _ctmStreamWriteUINT(self, u.i); +} + +//----------------------------------------------------------------------------- +// _ctmStreamReadSTRING() - Read a string value from a stream. The format of +// the string in the stream is: an unsigned integer (string length) followed by +// the string (without null termination). +//----------------------------------------------------------------------------- +void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue) +{ + CTMuint len; + + // Clear the old string + if(*aValue) + { + free(*aValue); + *aValue = (char *) 0; + } + + // Get string length + len = _ctmStreamReadUINT(self); + + // Read string + if(len > 0) + { + *aValue = (char *) malloc(len + 1); + if(*aValue) + { + _ctmStreamRead(self, (void *) *aValue, len); + (*aValue)[len] = 0; + } + } +} + +//----------------------------------------------------------------------------- +// _ctmStreamWriteSTRING() - Write a string value to a stream. The format of +// the string in the stream is: an unsigned integer (string length) followed by +// the string (without null termination). +//----------------------------------------------------------------------------- +void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue) +{ + CTMuint len; + + // Get string length + if(aValue) + len = strlen(aValue); + else + len = 0; + + // Write string length + _ctmStreamWriteUINT(self, len); + + // Write string + if(len > 0) + _ctmStreamWrite(self, (void *) aValue, len); +} + +//----------------------------------------------------------------------------- +// _ctmStreamReadPackedInts() - Read an compressed binary integer data array +// from a stream, and uncompress it. +//----------------------------------------------------------------------------- +int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, + CTMuint aCount, CTMuint aSize, CTMint aSignedInts) +{ + size_t packedSize, unpackedSize; + CTMuint i, k, x; + CTMint value; + unsigned char * packed, * tmp; + unsigned char props[5]; + int lzmaRes; + + // Read packed data size from the stream + packedSize = (size_t) _ctmStreamReadUINT(self); + + // Read LZMA compression props from the stream + _ctmStreamRead(self, (void *) props, 5); + + // Allocate memory and read the packed data from the stream + packed = (unsigned char *) malloc(packedSize); + if(!packed) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + _ctmStreamRead(self, (void *) packed, packedSize); + + // Allocate memory for interleaved array + tmp = (unsigned char *) malloc(aCount * aSize * 4); + if(!tmp) + { + free(packed); + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Uncompress + unpackedSize = aCount * aSize * 4; + lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed, + &packedSize, props, 5); + + // Free the packed array + free(packed); + + // Error? + if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4)) + { + self->mError = CTM_LZMA_ERROR; + free(tmp); + return CTM_FALSE; + } + + // Convert interleaved array to integers + for(i = 0; i < aCount; ++ i) + { + for(k = 0; k < aSize; ++ k) + { + value = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] | + (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) | + (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) | + (((CTMint) tmp[i + k * aCount]) << 24); + // Convert signed magnitude to two's complement? + if(aSignedInts) + { + x = (CTMuint) value; + value = (x & 1) ? -(CTMint)((x + 1) >> 1) : (CTMint)(x >> 1); + } + aData[i * aSize + k] = value; + } + } + + // Free the interleaved array + free(tmp); + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _ctmStreamWritePackedInts() - Compress a binary integer data array, and +// write it to a stream. +//----------------------------------------------------------------------------- +int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData, + CTMuint aCount, CTMuint aSize, CTMint aSignedInts) +{ + int lzmaRes, lzmaAlgo; + CTMuint i, k; + CTMint value; + size_t bufSize, outPropsSize; + unsigned char * packed, outProps[5], *tmp; +#ifdef __DEBUG_ + CTMuint negCount = 0; +#endif + + // Allocate memory for interleaved array + tmp = (unsigned char *) malloc(aCount * aSize * 4); + if(!tmp) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Convert integers to an interleaved array + for(i = 0; i < aCount; ++ i) + { + for(k = 0; k < aSize; ++ k) + { + value = aData[i * aSize + k]; + // Convert two's complement to signed magnitude? + if(aSignedInts) + value = value < 0 ? -1 - (value << 1) : value << 1; +#ifdef __DEBUG_ + else if(value < 0) + ++ negCount; +#endif + tmp[i + k * aCount + 3 * aCount * aSize] = value & 0x000000ff; + tmp[i + k * aCount + 2 * aCount * aSize] = (value >> 8) & 0x000000ff; + tmp[i + k * aCount + aCount * aSize] = (value >> 16) & 0x000000ff; + tmp[i + k * aCount] = (value >> 24) & 0x000000ff; + } + } + + // Allocate memory for the packed data + bufSize = 1000 + aCount * aSize * 4; + packed = (unsigned char *) malloc(bufSize); + if(!packed) + { + free(tmp); + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Call LZMA to compress + outPropsSize = 5; + lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1); + lzmaRes = LzmaCompress(packed, + &bufSize, + (const unsigned char *) tmp, + aCount * aSize * 4, + outProps, + &outPropsSize, + self->mCompressionLevel, // Level (0-9) + 0, -1, -1, -1, -1, -1, // Default values (set by level) + lzmaAlgo // Algorithm (0 = fast, 1 = normal) + ); + + // Free temporary array + free(tmp); + + // Error? + if(lzmaRes != SZ_OK) + { + self->mError = CTM_LZMA_ERROR; + free(packed); + return CTM_FALSE; + } + +#ifdef __DEBUG_ + printf("%d->%d bytes (%d negative words)\n", aCount * aSize * 4, (int) bufSize, negCount); +#endif + + // Write packed data size to the stream + _ctmStreamWriteUINT(self, (CTMuint) bufSize); + + // Write LZMA compression props to the stream + _ctmStreamWrite(self, (void *) outProps, 5); + + // Write the packed data to the stream + _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize); + + // Free the packed data + free(packed); + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _ctmStreamReadPackedFloats() - Read an compressed binary float data array +// from a stream, and uncompress it. +//----------------------------------------------------------------------------- +int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, + CTMuint aCount, CTMuint aSize) +{ + CTMuint i, k; + size_t packedSize, unpackedSize; + union { + CTMfloat f; + CTMint i; + } value; + unsigned char * packed, * tmp; + unsigned char props[5]; + int lzmaRes; + + // Read packed data size from the stream + packedSize = (size_t) _ctmStreamReadUINT(self); + + // Read LZMA compression props from the stream + _ctmStreamRead(self, (void *) props, 5); + + // Allocate memory and read the packed data from the stream + packed = (unsigned char *) malloc(packedSize); + if(!packed) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + _ctmStreamRead(self, (void *) packed, packedSize); + + // Allocate memory for interleaved array + tmp = (unsigned char *) malloc(aCount * aSize * 4); + if(!tmp) + { + free(packed); + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Uncompress + unpackedSize = aCount * aSize * 4; + lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed, + &packedSize, props, 5); + + // Free the packed array + free(packed); + + // Error? + if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4)) + { + self->mError = CTM_LZMA_ERROR; + free(tmp); + return CTM_FALSE; + } + + // Convert interleaved array to floats + for(i = 0; i < aCount; ++ i) + { + for(k = 0; k < aSize; ++ k) + { + value.i = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] | + (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) | + (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) | + (((CTMint) tmp[i + k * aCount]) << 24); + aData[i * aSize + k] = value.f; + } + } + + // Free the interleaved array + free(tmp); + + return CTM_TRUE; +} + +//----------------------------------------------------------------------------- +// _ctmStreamWritePackedFloats() - Compress a binary float data array, and +// write it to a stream. +//----------------------------------------------------------------------------- +int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData, + CTMuint aCount, CTMuint aSize) +{ + int lzmaRes, lzmaAlgo; + CTMuint i, k; + union { + CTMfloat f; + CTMint i; + } value; + size_t bufSize, outPropsSize; + unsigned char * packed, outProps[5], *tmp; + + // Allocate memory for interleaved array + tmp = (unsigned char *) malloc(aCount * aSize * 4); + if(!tmp) + { + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Convert floats to an interleaved array + for(i = 0; i < aCount; ++ i) + { + for(k = 0; k < aSize; ++ k) + { + value.f = aData[i * aSize + k]; + tmp[i + k * aCount + 3 * aCount * aSize] = value.i & 0x000000ff; + tmp[i + k * aCount + 2 * aCount * aSize] = (value.i >> 8) & 0x000000ff; + tmp[i + k * aCount + aCount * aSize] = (value.i >> 16) & 0x000000ff; + tmp[i + k * aCount] = (value.i >> 24) & 0x000000ff; + } + } + + // Allocate memory for the packed data + bufSize = 1000 + aCount * aSize * 4; + packed = (unsigned char *) malloc(bufSize); + if(!packed) + { + free(tmp); + self->mError = CTM_OUT_OF_MEMORY; + return CTM_FALSE; + } + + // Call LZMA to compress + outPropsSize = 5; + lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1); + lzmaRes = LzmaCompress(packed, + &bufSize, + (const unsigned char *) tmp, + aCount * aSize * 4, + outProps, + &outPropsSize, + self->mCompressionLevel, // Level (0-9) + 0, -1, -1, -1, -1, -1, // Default values (set by level) + lzmaAlgo // Algorithm (0 = fast, 1 = normal) + ); + + // Free temporary array + free(tmp); + + // Error? + if(lzmaRes != SZ_OK) + { + self->mError = CTM_LZMA_ERROR; + free(packed); + return CTM_FALSE; + } + +#ifdef __DEBUG_ + printf("%d->%d bytes\n", aCount * aSize * 4, (int) bufSize); +#endif + + // Write packed data size to the stream + _ctmStreamWriteUINT(self, (CTMuint) bufSize); + + // Write LZMA compression props to the stream + _ctmStreamWrite(self, (void *) outProps, 5); + + // Write the packed data to the stream + _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize); + + // Free the packed data + free(packed); + + return CTM_TRUE; +} diff --git a/src/external/lib/macx/libopenctm.a b/src/external/lib/macx/libopenctm.a new file mode 100644 index 000000000..c2201c96f Binary files /dev/null and b/src/external/lib/macx/libopenctm.a differ