goat3d
changeset 14:188c697b3b49
- added a document describing the goat3d file format chunk hierarchy
- started an alternative XML-based file format
- added the openctm library
line diff
1.1 --- a/.hgignore Tue Sep 10 15:29:45 2013 +0300 1.2 +++ b/.hgignore Thu Sep 26 04:47:05 2013 +0300 1.3 @@ -9,3 +9,4 @@ 1.4 \.suo$ 1.5 x64/ 1.6 \.tlog$ 1.7 +^tags$
2.1 --- a/Makefile Tue Sep 10 15:29:45 2013 +0300 2.2 +++ b/Makefile Thu Sep 26 04:47:05 2013 +0300 2.3 @@ -8,6 +8,11 @@ 2.4 obj = $(src:.cc=.o) 2.5 dep = $(obj:.o=.d) 2.6 2.7 +openctm = libs/openctm/libopenctm.a 2.8 + 2.9 +extinc = -Ilibs/openctm 2.10 +extlibs = $(openctm) 2.11 + 2.12 name = goat3d 2.13 so_major = 0 2.14 so_minor = 1 2.15 @@ -26,18 +31,21 @@ 2.16 pic = -fPIC 2.17 endif 2.18 2.19 -CXXFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic) 2.20 -LDFLAGS = -lvmath -lanim 2.21 +CXXFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic) $(extinc) 2.22 +LDFLAGS = $(extlibs) -lvmath -lanim 2.23 2.24 .PHONY: all 2.25 all: $(lib_so) $(lib_a) 2.26 2.27 -$(lib_so): $(obj) 2.28 +$(lib_so): $(obj) $(extlibs) 2.29 $(CXX) -o $@ $(shared) $(obj) $(LDFLAGS) 2.30 2.31 -$(lib_a): $(obj) 2.32 +$(lib_a): $(obj) $(extlibs) 2.33 $(AR) rcs $@ $(obj) 2.34 2.35 +$(openctm): 2.36 + $(MAKE) -C libs/openctm 2.37 + 2.38 -include $(dep) 2.39 2.40 %.d: %.cc
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/doc/goatfmt Thu Sep 26 04:47:05 2013 +0300 3.3 @@ -0,0 +1,110 @@ 3.4 +Chunk structure 3.5 +--------------- 3.6 + 3.7 +Leaf nodes which carry actual data are marked with <SINGLE_CHILD>, or 3.8 +[MULTIPLE_CHILDREN]. Where choice is involved, options are seperated with the | 3.9 +symbol. 3.10 + 3.11 +SCENE 3.12 + +--ENV 3.13 + | +--AMBIENT 3.14 + | | +--<FLOAT3> 3.15 + | +--FOG 3.16 + | +--FOG_COLOR 3.17 + | | +--<FLOAT3> 3.18 + | +--FOG_EXP 3.19 + | +--<FLOAT> 3.20 + +--MTL 3.21 + | +--MTL_NAME 3.22 + | | +--<STRING> 3.23 + | +--MTL_ATTR 3.24 + | +--MTL_ATTR_NAME 3.25 + | | +--<STRING> 3.26 + | +--MTL_ATTR_VAL 3.27 + | | +--<FLOAT|FLOAT3|FLOAT4> 3.28 + | +--MTL_ATTR_MAP 3.29 + | +--<STRING> (filename) 3.30 + +--MESH 3.31 + | +--MESH_NAME 3.32 + | | +--<STRING> 3.33 + | +--MESH_MATERIAL 3.34 + | | +--<STRING> (material name) 3.35 + | +--MESH_VERTEX_LIST 3.36 + | | +--[FLOAT3] 3.37 + | +--MESH_NORMAL_LIST 3.38 + | | +--[FLOAT3] 3.39 + | +--MESH_TANGENT_LIST 3.40 + | | +--[FLOAT3] 3.41 + | +--MESH_TEXCOORD_LIST 3.42 + | | +--[FLOAT3] 3.43 + | +--MESH_SKINWEIGHT_LIST 3.44 + | | +--[FLOAT4] (vector elements are the 4 skin weights/vertex) 3.45 + | +--MESH_SKINMATRIX_LIST 3.46 + | | +--[INT4] (vector elements are the 4 matrix indices/vertex) 3.47 + | +--MESH_COLOR_LIST 3.48 + | | +--[FLOAT4] 3.49 + | +--MESH_BONES_LIST 3.50 + | | +--[INT|STRING] (list of bone nodes by name or index) 3.51 + | +--MESH_FACE_LIST 3.52 + | | +--MESH_FACE 3.53 + | | +--[INT] (three INT chunks for the vertex indices) 3.54 + | +--MESH_FILE 3.55 + | +--<STRING> (filename of mesh file to get all the data from) 3.56 + +--LIGHT 3.57 + | +--LIGHT_NAME 3.58 + | | +--<STRING> 3.59 + | +--LIGHT_POS 3.60 + | | +--<FLOAT3> 3.61 + | +--LIGHT_COLOR 3.62 + | | +--<FLOAT3> 3.63 + | +--LIGHT_ATTEN 3.64 + | | +--<FLOAT3> (constant, linear, and quadratic attenuation) 3.65 + | +--LIGHT_DISTANCE 3.66 + | | +--<FLOAT> 3.67 + | +--LIGHT_DIR 3.68 + | | +--<FLOAT3> 3.69 + | +--LIGHT_CONE_INNER 3.70 + | | +--<FLOAT> 3.71 + | +--LIGHT_CONE_OUTER 3.72 + | +--<FLOAT> 3.73 + +--CAMERA 3.74 + | +--CAMERA_NAME 3.75 + | | +--<STRING> 3.76 + | +--CAMERA_POS 3.77 + | | +--<FLOAT3> 3.78 + | +--CAMERA_TARGET 3.79 + | | +--<FLOAT3> 3.80 + | +--CAMERA_FOV 3.81 + | | +--<FLOAT> 3.82 + | +--CAMERA_NEARCLIP 3.83 + | | +--<FLOAT> 3.84 + | +--CAMERA_FARCLIP 3.85 + | +--<FLOAT> 3.86 + +--NODE 3.87 + +--NODE_NAME 3.88 + | +--<STRING> 3.89 + +--NODE_PARENT 3.90 + | +--<INT|STRING> 3.91 + +--NODE_MESH|NODE_LIGHT|NODE_CAMERA 3.92 + | +--<INT|STRING> 3.93 + +--NODE_POS 3.94 + | +--<FLOAT3> 3.95 + +--NODE_ROT 3.96 + | +--<FLOAT4> ([x, y, z], w <- real part) 3.97 + +--NODE_SCALE 3.98 + | +--<FLOAT3> 3.99 + +--NODE_PIVOT 3.100 + | +--<FLOAT3> 3.101 + +--NODE_MATRIX0 3.102 + | +--<FLOAT4> (first row) 3.103 + +--NODE_MATRIX1 3.104 + | +--<FLOAT4> (second row) 3.105 + +--NODE_MATRIX2 3.106 + +--<FLOAT4> (third row) 3.107 + 3.108 +NOTES: 3.109 + * Name chunks are mandatory. If something doesn't have a name, one must be made 3.110 + up, even if it's just "object%d". 3.111 + * In node chunks, both POS/ROT/SCALE, and MATRIX0/MATRIX1/MATRIX2 are mandatory 3.112 + and they must agree. Makes it easy for the reader to pick the transformation 3.113 + data in whichever way is more convenient.
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/libs/openctm/LICENSE.txt Thu Sep 26 04:47:05 2013 +0300 4.3 @@ -0,0 +1,20 @@ 4.4 +Copyright (c) 2009-2010 Marcus Geelnard 4.5 + 4.6 +This software is provided 'as-is', without any express or implied 4.7 +warranty. In no event will the authors be held liable for any damages 4.8 +arising from the use of this software. 4.9 + 4.10 +Permission is granted to anyone to use this software for any purpose, 4.11 +including commercial applications, and to alter it and redistribute it 4.12 +freely, subject to the following restrictions: 4.13 + 4.14 + 1. The origin of this software must not be misrepresented; you must not 4.15 + claim that you wrote the original software. If you use this software 4.16 + in a product, an acknowledgment in the product documentation would be 4.17 + appreciated but is not required. 4.18 + 4.19 + 2. Altered source versions must be plainly marked as such, and must not 4.20 + be misrepresented as being the original software. 4.21 + 4.22 + 3. This notice may not be removed or altered from any source 4.23 + distribution.
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/libs/openctm/Makefile Thu Sep 26 04:47:05 2013 +0300 5.3 @@ -0,0 +1,16 @@ 5.4 +src = $(wildcard *.c) $(wildcard liblzma/*.c) 5.5 +obj = $(src:.c=.o) 5.6 +lib = libopenctm.a 5.7 + 5.8 +ifneq ($(shell uname -s), Darwin) 5.9 + pic = -fPIC 5.10 +endif 5.11 + 5.12 +CFLAGS = -g -Iliblzma $(pic) 5.13 + 5.14 +$(lib): $(obj) 5.15 + $(AR) rcs $@ $(obj) 5.16 + 5.17 +.PHONY: clean 5.18 +clean: 5.19 + rm -f $(obj) $(lib)
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/libs/openctm/README.txt Thu Sep 26 04:47:05 2013 +0300 6.3 @@ -0,0 +1,152 @@ 6.4 +1. INTRODUCTION 6.5 +=============== 6.6 + 6.7 +Welcome to OpenCTM! 6.8 + 6.9 +OpenCTM is a file format, a software library and a tool set for compression of 6.10 +3D triangle meshes. The geometry is compressed to a fraction of comparable file 6.11 +formats (3DS, STL, COLLADA, VRML...), and the format is easily accessible 6.12 +through a simple, portable API. 6.13 + 6.14 +The library is written in portable C (C99), and should compile nicely on any 6.15 +32/64-bit system regardless of endianity (big endian or little endian). 6.16 + 6.17 + 6.18 +2. LICENSE 6.19 +========== 6.20 + 6.21 +The OpenCTM API and the OpenCTM tools are released under the zlib/libpng 6.22 +license (see LICENSE.txt). 6.23 + 6.24 +3. CREDITS 6.25 +========== 6.26 + 6.27 +Many people have helped out in the development process of OpenCTM, with 6.28 +valuable feedback, programming efforts, test models and conceptual ideas. 6.29 +Also, OpenCTM relies heavily on many other open source projects. 6.30 + 6.31 +Here is an incomplete list of persons that deserve credit: 6.32 + 6.33 +- Igor Pavlov (LZMA library) 6.34 +- Jonas Innala (COLLADA importer, Maya exporter plugin) 6.35 +- Ilian Dinev (help with the OpenCTM file format design and the LWO loader) 6.36 +- Lee Thomason (TinyXML) 6.37 +- Diego Nehab (RPly - for loading PLY files) 6.38 +- Lev Povalahev, Marcelo E. Magallon, Milan Ikits (GLEW) 6.39 +- Thomas G. Lane, Guido Vollbeding (libjpeg) 6.40 +- Jean-loup Gailly, Mark Adler (zlib) 6.41 +- Daniel Karling (pnglite) 6.42 + 6.43 +During the development of OpenCTM, the following software has been used 6.44 +extensively: 6.45 + 6.46 +- Ubuntu (www.ubuntu.com) 6.47 +- Blender (www.blender.org) 6.48 +- GCC (gcc.gnu.org) 6.49 +- SciTE (www.scintilla.org/SciTE.html) 6.50 +- Notepad++ (notepad-plus.sourceforge.net) 6.51 +- Smultron (smultron.sourceforge.net) 6.52 + 6.53 +Legal notices: 6.54 + 6.55 +- This software is based in part on the work of the Independent JPEG Group. 6.56 + 6.57 + 6.58 +4. CHANGES 6.59 +========== 6.60 + 6.61 +v1.0.3 - 2010.01.15 6.62 +------------------- 6.63 +- Added support for PNG format textures (ctmviewer). 6.64 + 6.65 +- Added support for LightWave LWO files (ctmconv and ctmviewer). 6.66 + 6.67 +- Added support for Geomview OFF files, e.g. as used by the Princeton Shape 6.68 + Benchmark (ctmconv and ctmviewer). 6.69 + 6.70 +- Improved the OBJ file loader (ctmviewer and ctmconv). 6.71 + 6.72 +- Experimental support for VRML 2.0 files - export only (ctmconv and ctmviewer). 6.73 + 6.74 +- Made it possible to run ctmviewer without command line arguments. 6.75 + 6.76 +- Improved the normal calculation algorithm (ctmviewer and ctmconv). 6.77 + 6.78 +- Normals are no longer exported if no normals were present in the input file 6.79 + (ctmviewer). 6.80 + 6.81 + 6.82 +v1.0.2 - 2009.12.13 6.83 +------------------- 6.84 +- Added an OpenCTM exporter plugin for Maya [Jonas Innala]. 6.85 + 6.86 +- Added the possiblity to save and load files from ctmviewer, effectively 6.87 + turning it into a quick and simple converter tool (without all the options 6.88 + in the ctmconv program, though). 6.89 + 6.90 +- Added a function to load texture files from ctmviewer. 6.91 + 6.92 +- Improved the camera control in ctmviewer (panning with the right mouse 6.93 + button, zooming with the middle mouse button and the mouse wheel, feature 6.94 + focusing by double clicking, Y/Z up axis selection and "fit to screen" 6.95 + function). 6.96 + 6.97 +- Added a GUI dialog for showing errors in ctmviewer (this is especially useful 6.98 + under Windows, where console output is disabeled). 6.99 + 6.100 +- Added an option for calculating the normals in ctmconv (if the input file 6.101 + does not have normals). 6.102 + 6.103 +- Added options for turning off normals, texture coordinates and/or vertex 6.104 + colors for the output file in ctmconv. 6.105 + 6.106 +- Added manuals for ctmviewer and ctmconv (man pages). 6.107 + 6.108 +- Added a "make install" build target for Mac OS X and Linux for simple system 6.109 + wide installation (see COMPILING.txt). 6.110 + 6.111 +- NOTE: The Linux/X11 version of ctmviewer now reqires GTK+ 2.0. 6.112 + 6.113 + 6.114 +v1.0.1 - 2009.11.15 6.115 +------------------- 6.116 +- Notable reduction of the memory footprint by tuning of the LZMA compression 6.117 + parameters. 6.118 + 6.119 +- Added a Wavefront OBJ file importer/exporter. 6.120 + 6.121 +- Some improvements to ctmviewer and ctmconv. 6.122 + 6.123 +- Some directory structure and build system cleanups. 6.124 + 6.125 + 6.126 +v1.0 - 2009.11.09 6.127 +----------------- 6.128 +- Added a COLLADA converter module to the ctmconv program [Jonas Innala]. 6.129 + 6.130 +- Added Python bindings and a demo Python program. 6.131 + 6.132 +- Improved the internal mesh integrity checking, to minimize the risk of invalid 6.133 + data processing. 6.134 + 6.135 +- Improved the file format specification document. 6.136 + 6.137 + 6.138 +v0.8 (beta) - 2009.09.14 6.139 +------------------------ 6.140 +- Introduced a new API function for controlling the compression level 6.141 + (ctmCompressionLevel), and set the default compression level to 5 (rather 6.142 + than 9, which would eat a lot of memory, usally without much difference). 6.143 + 6.144 +- Changed the name "texture map" in the API to "UV map" (and all 6.145 + corresponding constant and function names). This is more in line with 6.146 + the nomenclature of most 3D authoring software, and avoids the confusion 6.147 + with the term texture mapping in 3D hardware (which is not limited to 6.148 + 2D UV mapping coordinates). 6.149 + 6.150 +- A few updates to the documentation. 6.151 + 6.152 + 6.153 +v0.7 (beta) - 2009.08.29 6.154 +------------------------ 6.155 +- This was the first public release of OpenCTM.
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/libs/openctm/compressMG1.c Thu Sep 26 04:47:05 2013 +0300 7.3 @@ -0,0 +1,324 @@ 7.4 +//----------------------------------------------------------------------------- 7.5 +// Product: OpenCTM 7.6 +// File: compressMG1.c 7.7 +// Description: Implementation of the MG1 compression method. 7.8 +//----------------------------------------------------------------------------- 7.9 +// Copyright (c) 2009-2010 Marcus Geelnard 7.10 +// 7.11 +// This software is provided 'as-is', without any express or implied 7.12 +// warranty. In no event will the authors be held liable for any damages 7.13 +// arising from the use of this software. 7.14 +// 7.15 +// Permission is granted to anyone to use this software for any purpose, 7.16 +// including commercial applications, and to alter it and redistribute it 7.17 +// freely, subject to the following restrictions: 7.18 +// 7.19 +// 1. The origin of this software must not be misrepresented; you must not 7.20 +// claim that you wrote the original software. If you use this software 7.21 +// in a product, an acknowledgment in the product documentation would be 7.22 +// appreciated but is not required. 7.23 +// 7.24 +// 2. Altered source versions must be plainly marked as such, and must not 7.25 +// be misrepresented as being the original software. 7.26 +// 7.27 +// 3. This notice may not be removed or altered from any source 7.28 +// distribution. 7.29 +//----------------------------------------------------------------------------- 7.30 + 7.31 +#include <stdlib.h> 7.32 +#include <math.h> 7.33 +#include "openctm.h" 7.34 +#include "internal.h" 7.35 + 7.36 +#ifdef __DEBUG_ 7.37 +#include <stdio.h> 7.38 +#endif 7.39 + 7.40 + 7.41 +//----------------------------------------------------------------------------- 7.42 +// _compareTriangle() - Comparator for the triangle sorting. 7.43 +//----------------------------------------------------------------------------- 7.44 +static int _compareTriangle(const void * elem1, const void * elem2) 7.45 +{ 7.46 + CTMuint * tri1 = (CTMuint *) elem1; 7.47 + CTMuint * tri2 = (CTMuint *) elem2; 7.48 + if(tri1[0] != tri2[0]) 7.49 + return tri1[0] - tri2[0]; 7.50 + else 7.51 + return tri1[1] - tri2[1]; 7.52 +} 7.53 + 7.54 +//----------------------------------------------------------------------------- 7.55 +// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal 7.56 +// compression. 7.57 +//----------------------------------------------------------------------------- 7.58 +static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices) 7.59 +{ 7.60 + CTMuint * tri, tmp, i; 7.61 + 7.62 + // Step 1: Make sure that the first index of each triangle is the smallest 7.63 + // one (rotate triangle nodes if necessary) 7.64 + for(i = 0; i < self->mTriangleCount; ++ i) 7.65 + { 7.66 + tri = &aIndices[i * 3]; 7.67 + if((tri[1] < tri[0]) && (tri[1] < tri[2])) 7.68 + { 7.69 + tmp = tri[0]; 7.70 + tri[0] = tri[1]; 7.71 + tri[1] = tri[2]; 7.72 + tri[2] = tmp; 7.73 + } 7.74 + else if((tri[2] < tri[0]) && (tri[2] < tri[1])) 7.75 + { 7.76 + tmp = tri[0]; 7.77 + tri[0] = tri[2]; 7.78 + tri[2] = tri[1]; 7.79 + tri[1] = tmp; 7.80 + } 7.81 + } 7.82 + 7.83 + // Step 2: Sort the triangles based on the first triangle index 7.84 + qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle); 7.85 +} 7.86 + 7.87 +//----------------------------------------------------------------------------- 7.88 +// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to 7.89 +// reduce data entropy. 7.90 +//----------------------------------------------------------------------------- 7.91 +static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices) 7.92 +{ 7.93 + CTMint i; 7.94 + for(i = self->mTriangleCount - 1; i >= 0; -- i) 7.95 + { 7.96 + // Step 1: Calculate delta from second triangle index to the previous 7.97 + // second triangle index, if the previous triangle shares the same first 7.98 + // index, otherwise calculate the delta to the first triangle index 7.99 + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) 7.100 + aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1]; 7.101 + else 7.102 + aIndices[i * 3 + 1] -= aIndices[i * 3]; 7.103 + 7.104 + // Step 2: Calculate delta from third triangle index to the first triangle 7.105 + // index 7.106 + aIndices[i * 3 + 2] -= aIndices[i * 3]; 7.107 + 7.108 + // Step 3: Calculate derivative of the first triangle index 7.109 + if(i >= 1) 7.110 + aIndices[i * 3] -= aIndices[(i - 1) * 3]; 7.111 + } 7.112 +} 7.113 + 7.114 +//----------------------------------------------------------------------------- 7.115 +// _ctmRestoreIndices() - Restore original indices (inverse derivative 7.116 +// operation). 7.117 +//----------------------------------------------------------------------------- 7.118 +static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices) 7.119 +{ 7.120 + CTMuint i; 7.121 + 7.122 + for(i = 0; i < self->mTriangleCount; ++ i) 7.123 + { 7.124 + // Step 1: Reverse derivative of the first triangle index 7.125 + if(i >= 1) 7.126 + aIndices[i * 3] += aIndices[(i - 1) * 3]; 7.127 + 7.128 + // Step 2: Reverse delta from third triangle index to the first triangle 7.129 + // index 7.130 + aIndices[i * 3 + 2] += aIndices[i * 3]; 7.131 + 7.132 + // Step 3: Reverse delta from second triangle index to the previous 7.133 + // second triangle index, if the previous triangle shares the same first 7.134 + // index, otherwise reverse the delta to the first triangle index 7.135 + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) 7.136 + aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1]; 7.137 + else 7.138 + aIndices[i * 3 + 1] += aIndices[i * 3]; 7.139 + } 7.140 +} 7.141 + 7.142 +//----------------------------------------------------------------------------- 7.143 +// _ctmCompressMesh_MG1() - Compress the mesh that is stored in the CTM 7.144 +// context, and write it the the output stream in the CTM context. 7.145 +//----------------------------------------------------------------------------- 7.146 +int _ctmCompressMesh_MG1(_CTMcontext * self) 7.147 +{ 7.148 + CTMuint * indices; 7.149 + _CTMfloatmap * map; 7.150 + CTMuint i; 7.151 + 7.152 +#ifdef __DEBUG_ 7.153 + printf("COMPRESSION METHOD: MG1\n"); 7.154 +#endif 7.155 + 7.156 + // Perpare (sort) indices 7.157 + indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); 7.158 + if(!indices) 7.159 + { 7.160 + self->mError = CTM_OUT_OF_MEMORY; 7.161 + return CTM_FALSE; 7.162 + } 7.163 + for(i = 0; i < self->mTriangleCount * 3; ++ i) 7.164 + indices[i] = self->mIndices[i]; 7.165 + _ctmReArrangeTriangles(self, indices); 7.166 + 7.167 + // Calculate index deltas (entropy-reduction) 7.168 + _ctmMakeIndexDeltas(self, indices); 7.169 + 7.170 + // Write triangle indices 7.171 +#ifdef __DEBUG_ 7.172 + printf("Inidices: "); 7.173 +#endif 7.174 + _ctmStreamWrite(self, (void *) "INDX", 4); 7.175 + if(!_ctmStreamWritePackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE)) 7.176 + { 7.177 + free((void *) indices); 7.178 + return CTM_FALSE; 7.179 + } 7.180 + 7.181 + // Free temporary resources 7.182 + free((void *) indices); 7.183 + 7.184 + // Write vertices 7.185 +#ifdef __DEBUG_ 7.186 + printf("Vertices: "); 7.187 +#endif 7.188 + _ctmStreamWrite(self, (void *) "VERT", 4); 7.189 + if(!_ctmStreamWritePackedFloats(self, self->mVertices, self->mVertexCount * 3, 1)) 7.190 + { 7.191 + free((void *) indices); 7.192 + return CTM_FALSE; 7.193 + } 7.194 + 7.195 + // Write normals 7.196 + if(self->mNormals) 7.197 + { 7.198 +#ifdef __DEBUG_ 7.199 + printf("Normals: "); 7.200 +#endif 7.201 + _ctmStreamWrite(self, (void *) "NORM", 4); 7.202 + if(!_ctmStreamWritePackedFloats(self, self->mNormals, self->mVertexCount, 3)) 7.203 + return CTM_FALSE; 7.204 + } 7.205 + 7.206 + // Write UV maps 7.207 + map = self->mUVMaps; 7.208 + while(map) 7.209 + { 7.210 +#ifdef __DEBUG_ 7.211 + printf("UV coordinates (%s): ", map->mName ? map->mName : "no name"); 7.212 +#endif 7.213 + _ctmStreamWrite(self, (void *) "TEXC", 4); 7.214 + _ctmStreamWriteSTRING(self, map->mName); 7.215 + _ctmStreamWriteSTRING(self, map->mFileName); 7.216 + if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 2)) 7.217 + return CTM_FALSE; 7.218 + map = map->mNext; 7.219 + } 7.220 + 7.221 + // Write attribute maps 7.222 + map = self->mAttribMaps; 7.223 + while(map) 7.224 + { 7.225 +#ifdef __DEBUG_ 7.226 + printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name"); 7.227 +#endif 7.228 + _ctmStreamWrite(self, (void *) "ATTR", 4); 7.229 + _ctmStreamWriteSTRING(self, map->mName); 7.230 + if(!_ctmStreamWritePackedFloats(self, map->mValues, self->mVertexCount, 4)) 7.231 + return CTM_FALSE; 7.232 + map = map->mNext; 7.233 + } 7.234 + 7.235 + return CTM_TRUE; 7.236 +} 7.237 + 7.238 +//----------------------------------------------------------------------------- 7.239 +// _ctmUncompressMesh_MG1() - Uncmpress the mesh from the input stream in the 7.240 +// CTM context, and store the resulting mesh in the CTM context. 7.241 +//----------------------------------------------------------------------------- 7.242 +int _ctmUncompressMesh_MG1(_CTMcontext * self) 7.243 +{ 7.244 + CTMuint * indices; 7.245 + _CTMfloatmap * map; 7.246 + CTMuint i; 7.247 + 7.248 + // Allocate memory for the indices 7.249 + indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); 7.250 + if(!indices) 7.251 + { 7.252 + self->mError = CTM_OUT_OF_MEMORY; 7.253 + return CTM_FALSE; 7.254 + } 7.255 + 7.256 + // Read triangle indices 7.257 + if(_ctmStreamReadUINT(self) != FOURCC("INDX")) 7.258 + { 7.259 + self->mError = CTM_BAD_FORMAT; 7.260 + free(indices); 7.261 + return CTM_FALSE; 7.262 + } 7.263 + if(!_ctmStreamReadPackedInts(self, (CTMint *) indices, self->mTriangleCount, 3, CTM_FALSE)) 7.264 + return CTM_FALSE; 7.265 + 7.266 + // Restore indices 7.267 + _ctmRestoreIndices(self, indices); 7.268 + for(i = 0; i < self->mTriangleCount * 3; ++ i) 7.269 + self->mIndices[i] = indices[i]; 7.270 + 7.271 + // Free temporary resources 7.272 + free(indices); 7.273 + 7.274 + // Read vertices 7.275 + if(_ctmStreamReadUINT(self) != FOURCC("VERT")) 7.276 + { 7.277 + self->mError = CTM_BAD_FORMAT; 7.278 + return CTM_FALSE; 7.279 + } 7.280 + if(!_ctmStreamReadPackedFloats(self, self->mVertices, self->mVertexCount * 3, 1)) 7.281 + return CTM_FALSE; 7.282 + 7.283 + // Read normals 7.284 + if(self->mNormals) 7.285 + { 7.286 + if(_ctmStreamReadUINT(self) != FOURCC("NORM")) 7.287 + { 7.288 + self->mError = CTM_BAD_FORMAT; 7.289 + return CTM_FALSE; 7.290 + } 7.291 + if(!_ctmStreamReadPackedFloats(self, self->mNormals, self->mVertexCount, 3)) 7.292 + return CTM_FALSE; 7.293 + } 7.294 + 7.295 + // Read UV maps 7.296 + map = self->mUVMaps; 7.297 + while(map) 7.298 + { 7.299 + if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) 7.300 + { 7.301 + self->mError = CTM_BAD_FORMAT; 7.302 + return 0; 7.303 + } 7.304 + _ctmStreamReadSTRING(self, &map->mName); 7.305 + _ctmStreamReadSTRING(self, &map->mFileName); 7.306 + if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 2)) 7.307 + return CTM_FALSE; 7.308 + map = map->mNext; 7.309 + } 7.310 + 7.311 + // Read vertex attribute maps 7.312 + map = self->mAttribMaps; 7.313 + while(map) 7.314 + { 7.315 + if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) 7.316 + { 7.317 + self->mError = CTM_BAD_FORMAT; 7.318 + return 0; 7.319 + } 7.320 + _ctmStreamReadSTRING(self, &map->mName); 7.321 + if(!_ctmStreamReadPackedFloats(self, map->mValues, self->mVertexCount, 4)) 7.322 + return CTM_FALSE; 7.323 + map = map->mNext; 7.324 + } 7.325 + 7.326 + return CTM_TRUE; 7.327 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/libs/openctm/compressMG2.c Thu Sep 26 04:47:05 2013 +0300 8.3 @@ -0,0 +1,1319 @@ 8.4 +//----------------------------------------------------------------------------- 8.5 +// Product: OpenCTM 8.6 +// File: compressMG2.c 8.7 +// Description: Implementation of the MG2 compression method. 8.8 +//----------------------------------------------------------------------------- 8.9 +// Copyright (c) 2009-2010 Marcus Geelnard 8.10 +// 8.11 +// This software is provided 'as-is', without any express or implied 8.12 +// warranty. In no event will the authors be held liable for any damages 8.13 +// arising from the use of this software. 8.14 +// 8.15 +// Permission is granted to anyone to use this software for any purpose, 8.16 +// including commercial applications, and to alter it and redistribute it 8.17 +// freely, subject to the following restrictions: 8.18 +// 8.19 +// 1. The origin of this software must not be misrepresented; you must not 8.20 +// claim that you wrote the original software. If you use this software 8.21 +// in a product, an acknowledgment in the product documentation would be 8.22 +// appreciated but is not required. 8.23 +// 8.24 +// 2. Altered source versions must be plainly marked as such, and must not 8.25 +// be misrepresented as being the original software. 8.26 +// 8.27 +// 3. This notice may not be removed or altered from any source 8.28 +// distribution. 8.29 +//----------------------------------------------------------------------------- 8.30 + 8.31 +#include <stdlib.h> 8.32 +#include <math.h> 8.33 +#include "openctm.h" 8.34 +#include "internal.h" 8.35 + 8.36 +#ifdef __DEBUG_ 8.37 +#include <stdio.h> 8.38 +#endif 8.39 + 8.40 +// We need PI 8.41 +#ifndef PI 8.42 +#define PI 3.141592653589793238462643f 8.43 +#endif 8.44 + 8.45 + 8.46 +//----------------------------------------------------------------------------- 8.47 +// _CTMgrid - 3D space subdivision grid. 8.48 +//----------------------------------------------------------------------------- 8.49 +typedef struct { 8.50 + // Axis-aligned boudning box for the grid. 8.51 + CTMfloat mMin[3]; 8.52 + CTMfloat mMax[3]; 8.53 + 8.54 + // How many divisions per axis (minimum 1). 8.55 + CTMuint mDivision[3]; 8.56 + 8.57 + // Size of each grid box. 8.58 + CTMfloat mSize[3]; 8.59 +} _CTMgrid; 8.60 + 8.61 +//----------------------------------------------------------------------------- 8.62 +// _CTMsortvertex - Vertex information. 8.63 +//----------------------------------------------------------------------------- 8.64 +typedef struct { 8.65 + // Vertex X coordinate (used for sorting). 8.66 + CTMfloat x; 8.67 + 8.68 + // Grid index. This is the index into the 3D space subdivision grid. 8.69 + CTMuint mGridIndex; 8.70 + 8.71 + // Original index (before sorting). 8.72 + CTMuint mOriginalIndex; 8.73 +} _CTMsortvertex; 8.74 + 8.75 +//----------------------------------------------------------------------------- 8.76 +// _ctmSetupGrid() - Setup the 3D space subdivision grid. 8.77 +//----------------------------------------------------------------------------- 8.78 +static void _ctmSetupGrid(_CTMcontext * self, _CTMgrid * aGrid) 8.79 +{ 8.80 + CTMuint i; 8.81 + CTMfloat factor[3], sum, wantedGrids; 8.82 + 8.83 + // Calculate the mesh bounding box 8.84 + aGrid->mMin[0] = aGrid->mMax[0] = self->mVertices[0]; 8.85 + aGrid->mMin[1] = aGrid->mMax[1] = self->mVertices[1]; 8.86 + aGrid->mMin[2] = aGrid->mMax[2] = self->mVertices[2]; 8.87 + for(i = 1; i < self->mVertexCount; ++ i) 8.88 + { 8.89 + if(self->mVertices[i * 3] < aGrid->mMin[0]) 8.90 + aGrid->mMin[0] = self->mVertices[i * 3]; 8.91 + else if(self->mVertices[i * 3] > aGrid->mMax[0]) 8.92 + aGrid->mMax[0] = self->mVertices[i * 3]; 8.93 + if(self->mVertices[i * 3 + 1] < aGrid->mMin[1]) 8.94 + aGrid->mMin[1] = self->mVertices[i * 3 + 1]; 8.95 + else if(self->mVertices[i * 3 + 1] > aGrid->mMax[1]) 8.96 + aGrid->mMax[1] = self->mVertices[i * 3 + 1]; 8.97 + if(self->mVertices[i * 3 + 2] < aGrid->mMin[2]) 8.98 + aGrid->mMin[2] = self->mVertices[i * 3 + 2]; 8.99 + else if(self->mVertices[i * 3 + 2] > aGrid->mMax[2]) 8.100 + aGrid->mMax[2] = self->mVertices[i * 3 + 2]; 8.101 + } 8.102 + 8.103 + // Determine optimal grid resolution, based on the number of vertices and 8.104 + // the bounding box. 8.105 + // NOTE: This algorithm is quite crude, and could very well be optimized for 8.106 + // better compression levels in the future without affecting the file format 8.107 + // or backward compatibility at all. 8.108 + for(i = 0; i < 3; ++ i) 8.109 + factor[i] = aGrid->mMax[i] - aGrid->mMin[i]; 8.110 + sum = factor[0] + factor[1] + factor[2]; 8.111 + if(sum > 1e-30f) 8.112 + { 8.113 + sum = 1.0f / sum; 8.114 + for(i = 0; i < 3; ++ i) 8.115 + factor[i] *= sum; 8.116 + wantedGrids = powf(100.0f * self->mVertexCount, 1.0f / 3.0f); 8.117 + for(i = 0; i < 3; ++ i) 8.118 + { 8.119 + aGrid->mDivision[i] = (CTMuint) ceilf(wantedGrids * factor[i]); 8.120 + if(aGrid->mDivision[i] < 1) 8.121 + aGrid->mDivision[i] = 1; 8.122 + } 8.123 + } 8.124 + else 8.125 + { 8.126 + aGrid->mDivision[0] = 4; 8.127 + aGrid->mDivision[1] = 4; 8.128 + aGrid->mDivision[2] = 4; 8.129 + } 8.130 +#ifdef __DEBUG_ 8.131 + printf("Division: (%d %d %d)\n", aGrid->mDivision[0], aGrid->mDivision[1], aGrid->mDivision[2]); 8.132 +#endif 8.133 + 8.134 + // Calculate grid sizes 8.135 + for(i = 0; i < 3; ++ i) 8.136 + aGrid->mSize[i] = (aGrid->mMax[i] - aGrid->mMin[i]) / aGrid->mDivision[i]; 8.137 +} 8.138 + 8.139 +//----------------------------------------------------------------------------- 8.140 +// _ctmPointToGridIdx() - Convert a point to a grid index. 8.141 +//----------------------------------------------------------------------------- 8.142 +static CTMuint _ctmPointToGridIdx(_CTMgrid * aGrid, CTMfloat * aPoint) 8.143 +{ 8.144 + CTMuint i, idx[3]; 8.145 + 8.146 + for(i = 0; i < 3; ++ i) 8.147 + { 8.148 + idx[i] = (CTMuint) floorf((aPoint[i] - aGrid->mMin[i]) / aGrid->mSize[i]); 8.149 + if(idx[i] >= aGrid->mDivision[i]) 8.150 + idx[i] = aGrid->mDivision[i] - 1; 8.151 + } 8.152 + 8.153 + return idx[0] + aGrid->mDivision[0] * (idx[1] + aGrid->mDivision[1] * idx[2]); 8.154 +} 8.155 + 8.156 +//----------------------------------------------------------------------------- 8.157 +// _ctmGridIdxToPoint() - Convert a grid index to a point (the min x/y/z for 8.158 +// the given grid box). 8.159 +//----------------------------------------------------------------------------- 8.160 +static void _ctmGridIdxToPoint(_CTMgrid * aGrid, CTMuint aIdx, CTMfloat * aPoint) 8.161 +{ 8.162 + CTMuint gridIdx[3], zdiv, ydiv, i; 8.163 + 8.164 + zdiv = aGrid->mDivision[0] * aGrid->mDivision[1]; 8.165 + ydiv = aGrid->mDivision[0]; 8.166 + 8.167 + gridIdx[2] = aIdx / zdiv; 8.168 + aIdx -= gridIdx[2] * zdiv; 8.169 + gridIdx[1] = aIdx / ydiv; 8.170 + aIdx -= gridIdx[1] * ydiv; 8.171 + gridIdx[0] = aIdx; 8.172 + 8.173 + for(i = 0; i < 3; ++ i) 8.174 + aPoint[i] = gridIdx[i] * aGrid->mSize[i] + aGrid->mMin[i]; 8.175 +} 8.176 + 8.177 +//----------------------------------------------------------------------------- 8.178 +// _compareVertex() - Comparator for the vertex sorting. 8.179 +//----------------------------------------------------------------------------- 8.180 +static int _compareVertex(const void * elem1, const void * elem2) 8.181 +{ 8.182 + _CTMsortvertex * v1 = (_CTMsortvertex *) elem1; 8.183 + _CTMsortvertex * v2 = (_CTMsortvertex *) elem2; 8.184 + if(v1->mGridIndex != v2->mGridIndex) 8.185 + return v1->mGridIndex - v2->mGridIndex; 8.186 + else if(v1->x < v2->x) 8.187 + return -1; 8.188 + else if(v1->x > v2->x) 8.189 + return 1; 8.190 + else 8.191 + return 0; 8.192 +} 8.193 + 8.194 +//----------------------------------------------------------------------------- 8.195 +// _ctmSortVertices() - Setup the vertex array. Assign each vertex to a grid 8.196 +// box, and sort all vertices. 8.197 +//----------------------------------------------------------------------------- 8.198 +static void _ctmSortVertices(_CTMcontext * self, _CTMsortvertex * aSortVertices, 8.199 + _CTMgrid * aGrid) 8.200 +{ 8.201 + CTMuint i; 8.202 + 8.203 + // Prepare sort vertex array 8.204 + for(i = 0; i < self->mVertexCount; ++ i) 8.205 + { 8.206 + // Store vertex properties in the sort vertex array 8.207 + aSortVertices[i].x = self->mVertices[i * 3]; 8.208 + aSortVertices[i].mGridIndex = _ctmPointToGridIdx(aGrid, &self->mVertices[i * 3]); 8.209 + aSortVertices[i].mOriginalIndex = i; 8.210 + } 8.211 + 8.212 + // Sort vertices. The elements are first sorted by their grid indices, and 8.213 + // scondly by their x coordinates. 8.214 + qsort((void *) aSortVertices, self->mVertexCount, sizeof(_CTMsortvertex), _compareVertex); 8.215 +} 8.216 + 8.217 +//----------------------------------------------------------------------------- 8.218 +// _ctmReIndexIndices() - Re-index all indices, based on the sorted vertices. 8.219 +//----------------------------------------------------------------------------- 8.220 +static int _ctmReIndexIndices(_CTMcontext * self, _CTMsortvertex * aSortVertices, 8.221 + CTMuint * aIndices) 8.222 +{ 8.223 + CTMuint i, * indexLUT; 8.224 + 8.225 + // Create temporary lookup-array, O(n) 8.226 + indexLUT = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); 8.227 + if(!indexLUT) 8.228 + { 8.229 + self->mError = CTM_OUT_OF_MEMORY; 8.230 + return CTM_FALSE; 8.231 + } 8.232 + for(i = 0; i < self->mVertexCount; ++ i) 8.233 + indexLUT[aSortVertices[i].mOriginalIndex] = i; 8.234 + 8.235 + // Convert old indices to new indices, O(n) 8.236 + for(i = 0; i < self->mTriangleCount * 3; ++ i) 8.237 + aIndices[i] = indexLUT[self->mIndices[i]]; 8.238 + 8.239 + // Free temporary lookup-array 8.240 + free((void *) indexLUT); 8.241 + 8.242 + return CTM_TRUE; 8.243 +} 8.244 + 8.245 +//----------------------------------------------------------------------------- 8.246 +// _compareTriangle() - Comparator for the triangle sorting. 8.247 +//----------------------------------------------------------------------------- 8.248 +static int _compareTriangle(const void * elem1, const void * elem2) 8.249 +{ 8.250 + CTMuint * tri1 = (CTMuint *) elem1; 8.251 + CTMuint * tri2 = (CTMuint *) elem2; 8.252 + if(tri1[0] != tri2[0]) 8.253 + return tri1[0] - tri2[0]; 8.254 + else 8.255 + return tri1[1] - tri2[1]; 8.256 +} 8.257 + 8.258 +//----------------------------------------------------------------------------- 8.259 +// _ctmReArrangeTriangles() - Re-arrange all triangles for optimal 8.260 +// compression. 8.261 +//----------------------------------------------------------------------------- 8.262 +static void _ctmReArrangeTriangles(_CTMcontext * self, CTMuint * aIndices) 8.263 +{ 8.264 + CTMuint * tri, tmp, i; 8.265 + 8.266 + // Step 1: Make sure that the first index of each triangle is the smallest 8.267 + // one (rotate triangle nodes if necessary) 8.268 + for(i = 0; i < self->mTriangleCount; ++ i) 8.269 + { 8.270 + tri = &aIndices[i * 3]; 8.271 + if((tri[1] < tri[0]) && (tri[1] < tri[2])) 8.272 + { 8.273 + tmp = tri[0]; 8.274 + tri[0] = tri[1]; 8.275 + tri[1] = tri[2]; 8.276 + tri[2] = tmp; 8.277 + } 8.278 + else if((tri[2] < tri[0]) && (tri[2] < tri[1])) 8.279 + { 8.280 + tmp = tri[0]; 8.281 + tri[0] = tri[2]; 8.282 + tri[2] = tri[1]; 8.283 + tri[1] = tmp; 8.284 + } 8.285 + } 8.286 + 8.287 + // Step 2: Sort the triangles based on the first triangle index 8.288 + qsort((void *) aIndices, self->mTriangleCount, sizeof(CTMuint) * 3, _compareTriangle); 8.289 +} 8.290 + 8.291 +//----------------------------------------------------------------------------- 8.292 +// _ctmMakeIndexDeltas() - Calculate various forms of derivatives in order to 8.293 +// reduce data entropy. 8.294 +//----------------------------------------------------------------------------- 8.295 +static void _ctmMakeIndexDeltas(_CTMcontext * self, CTMuint * aIndices) 8.296 +{ 8.297 + CTMint i; 8.298 + for(i = self->mTriangleCount - 1; i >= 0; -- i) 8.299 + { 8.300 + // Step 1: Calculate delta from second triangle index to the previous 8.301 + // second triangle index, if the previous triangle shares the same first 8.302 + // index, otherwise calculate the delta to the first triangle index 8.303 + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) 8.304 + aIndices[i * 3 + 1] -= aIndices[(i - 1) * 3 + 1]; 8.305 + else 8.306 + aIndices[i * 3 + 1] -= aIndices[i * 3]; 8.307 + 8.308 + // Step 2: Calculate delta from third triangle index to the first triangle 8.309 + // index 8.310 + aIndices[i * 3 + 2] -= aIndices[i * 3]; 8.311 + 8.312 + // Step 3: Calculate derivative of the first triangle index 8.313 + if(i >= 1) 8.314 + aIndices[i * 3] -= aIndices[(i - 1) * 3]; 8.315 + } 8.316 +} 8.317 + 8.318 +//----------------------------------------------------------------------------- 8.319 +// _ctmRestoreIndices() - Restore original indices (inverse derivative 8.320 +// operation). 8.321 +//----------------------------------------------------------------------------- 8.322 +static void _ctmRestoreIndices(_CTMcontext * self, CTMuint * aIndices) 8.323 +{ 8.324 + CTMuint i; 8.325 + 8.326 + for(i = 0; i < self->mTriangleCount; ++ i) 8.327 + { 8.328 + // Step 1: Reverse derivative of the first triangle index 8.329 + if(i >= 1) 8.330 + aIndices[i * 3] += aIndices[(i - 1) * 3]; 8.331 + 8.332 + // Step 2: Reverse delta from third triangle index to the first triangle 8.333 + // index 8.334 + aIndices[i * 3 + 2] += aIndices[i * 3]; 8.335 + 8.336 + // Step 3: Reverse delta from second triangle index to the previous 8.337 + // second triangle index, if the previous triangle shares the same first 8.338 + // index, otherwise reverse the delta to the first triangle index 8.339 + if((i >= 1) && (aIndices[i * 3] == aIndices[(i - 1) * 3])) 8.340 + aIndices[i * 3 + 1] += aIndices[(i - 1) * 3 + 1]; 8.341 + else 8.342 + aIndices[i * 3 + 1] += aIndices[i * 3]; 8.343 + } 8.344 +} 8.345 + 8.346 +//----------------------------------------------------------------------------- 8.347 +// _ctmMakeVertexDeltas() - Calculate various forms of derivatives in order to 8.348 +// reduce data entropy. 8.349 +//----------------------------------------------------------------------------- 8.350 +static void _ctmMakeVertexDeltas(_CTMcontext * self, CTMint * aIntVertices, 8.351 + _CTMsortvertex * aSortVertices, _CTMgrid * aGrid) 8.352 +{ 8.353 + CTMuint i, gridIdx, prevGridIndex, oldIdx; 8.354 + CTMfloat gridOrigin[3], scale; 8.355 + CTMint deltaX, prevDeltaX; 8.356 + 8.357 + // Vertex scaling factor 8.358 + scale = 1.0f / self->mVertexPrecision; 8.359 + 8.360 + prevGridIndex = 0x7fffffff; 8.361 + prevDeltaX = 0; 8.362 + for(i = 0; i < self->mVertexCount; ++ i) 8.363 + { 8.364 + // Get grid box origin 8.365 + gridIdx = aSortVertices[i].mGridIndex; 8.366 + _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin); 8.367 + 8.368 + // Get old vertex coordinate index (before vertex sorting) 8.369 + oldIdx = aSortVertices[i].mOriginalIndex; 8.370 + 8.371 + // Store delta to the grid box origin in the integer vertex array. For the 8.372 + // X axis (which is sorted) we also do the delta to the previous coordinate 8.373 + // in the box. 8.374 + deltaX = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3] - gridOrigin[0]) + 0.5f); 8.375 + if(gridIdx == prevGridIndex) 8.376 + aIntVertices[i * 3] = deltaX - prevDeltaX; 8.377 + else 8.378 + aIntVertices[i * 3] = deltaX; 8.379 + aIntVertices[i * 3 + 1] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 1] - gridOrigin[1]) + 0.5f); 8.380 + aIntVertices[i * 3 + 2] = (CTMint) floorf(scale * (self->mVertices[oldIdx * 3 + 2] - gridOrigin[2]) + 0.5f); 8.381 + 8.382 + prevGridIndex = gridIdx; 8.383 + prevDeltaX = deltaX; 8.384 + } 8.385 +} 8.386 + 8.387 +//----------------------------------------------------------------------------- 8.388 +// _ctmRestoreVertices() - Calculate inverse derivatives of the vertices. 8.389 +//----------------------------------------------------------------------------- 8.390 +static void _ctmRestoreVertices(_CTMcontext * self, CTMint * aIntVertices, 8.391 + CTMuint * aGridIndices, _CTMgrid * aGrid, CTMfloat * aVertices) 8.392 +{ 8.393 + CTMuint i, gridIdx, prevGridIndex; 8.394 + CTMfloat gridOrigin[3], scale; 8.395 + CTMint deltaX, prevDeltaX; 8.396 + 8.397 + scale = self->mVertexPrecision; 8.398 + 8.399 + prevGridIndex = 0x7fffffff; 8.400 + prevDeltaX = 0; 8.401 + for(i = 0; i < self->mVertexCount; ++ i) 8.402 + { 8.403 + // Get grid box origin 8.404 + gridIdx = aGridIndices[i]; 8.405 + _ctmGridIdxToPoint(aGrid, gridIdx, gridOrigin); 8.406 + 8.407 + // Restore original point 8.408 + deltaX = aIntVertices[i * 3]; 8.409 + if(gridIdx == prevGridIndex) 8.410 + deltaX += prevDeltaX; 8.411 + aVertices[i * 3] = scale * deltaX + gridOrigin[0]; 8.412 + aVertices[i * 3 + 1] = scale * aIntVertices[i * 3 + 1] + gridOrigin[1]; 8.413 + aVertices[i * 3 + 2] = scale * aIntVertices[i * 3 + 2] + gridOrigin[2]; 8.414 + 8.415 + prevGridIndex = gridIdx; 8.416 + prevDeltaX = deltaX; 8.417 + } 8.418 +} 8.419 + 8.420 +//----------------------------------------------------------------------------- 8.421 +// _ctmCalcSmoothNormals() - Calculate the smooth normals for a given mesh. 8.422 +// These are used as the nominal normals for normal deltas & reconstruction. 8.423 +//----------------------------------------------------------------------------- 8.424 +static void _ctmCalcSmoothNormals(_CTMcontext * self, CTMfloat * aVertices, 8.425 + CTMuint * aIndices, CTMfloat * aSmoothNormals) 8.426 +{ 8.427 + CTMuint i, j, k, tri[3]; 8.428 + CTMfloat len; 8.429 + CTMfloat v1[3], v2[3], n[3]; 8.430 + 8.431 + // Clear smooth normals array 8.432 + for(i = 0; i < 3 * self->mVertexCount; ++ i) 8.433 + aSmoothNormals[i] = 0.0f; 8.434 + 8.435 + // Calculate sums of all neigbouring triangle normals for each vertex 8.436 + for(i = 0; i < self->mTriangleCount; ++ i) 8.437 + { 8.438 + // Get triangle corner indices 8.439 + for(j = 0; j < 3; ++ j) 8.440 + tri[j] = aIndices[i * 3 + j]; 8.441 + 8.442 + // Calculate the normalized cross product of two triangle edges (i.e. the 8.443 + // flat triangle normal) 8.444 + for(j = 0; j < 3; ++ j) 8.445 + { 8.446 + v1[j] = aVertices[tri[1] * 3 + j] - aVertices[tri[0] * 3 + j]; 8.447 + v2[j] = aVertices[tri[2] * 3 + j] - aVertices[tri[0] * 3 + j]; 8.448 + } 8.449 + n[0] = v1[1] * v2[2] - v1[2] * v2[1]; 8.450 + n[1] = v1[2] * v2[0] - v1[0] * v2[2]; 8.451 + n[2] = v1[0] * v2[1] - v1[1] * v2[0]; 8.452 + len = sqrtf(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]); 8.453 + if(len > 1e-10f) 8.454 + len = 1.0f / len; 8.455 + else 8.456 + len = 1.0f; 8.457 + for(j = 0; j < 3; ++ j) 8.458 + n[j] *= len; 8.459 + 8.460 + // Add the flat normal to all three triangle vertices 8.461 + for(k = 0; k < 3; ++ k) 8.462 + for(j = 0; j < 3; ++ j) 8.463 + aSmoothNormals[tri[k] * 3 + j] += n[j]; 8.464 + } 8.465 + 8.466 + // Normalize the normal sums, which gives the unit length smooth normals 8.467 + for(i = 0; i < self->mVertexCount; ++ i) 8.468 + { 8.469 + len = sqrtf(aSmoothNormals[i * 3] * aSmoothNormals[i * 3] + 8.470 + aSmoothNormals[i * 3 + 1] * aSmoothNormals[i * 3 + 1] + 8.471 + aSmoothNormals[i * 3 + 2] * aSmoothNormals[i * 3 + 2]); 8.472 + if(len > 1e-10f) 8.473 + len = 1.0f / len; 8.474 + else 8.475 + len = 1.0f; 8.476 + for(j = 0; j < 3; ++ j) 8.477 + aSmoothNormals[i * 3 + j] *= len; 8.478 + } 8.479 +} 8.480 + 8.481 +//----------------------------------------------------------------------------- 8.482 +// _ctmMakeNormalCoordSys() - Create an ortho-normalized coordinate system 8.483 +// where the Z-axis is aligned with the given normal. 8.484 +// Note 1: This function is central to how the compressed normal data is 8.485 +// interpreted, and it can not be changed (mathematically) without making the 8.486 +// coder/decoder incompatible with other versions of the library! 8.487 +// Note 2: Since we do this for every single normal, this routine needs to be 8.488 +// fast. The current implementation uses: 12 MUL, 1 DIV, 1 SQRT, ~6 ADD. 8.489 +//----------------------------------------------------------------------------- 8.490 +static void _ctmMakeNormalCoordSys(CTMfloat * aNormal, CTMfloat * aBasisAxes) 8.491 +{ 8.492 + CTMfloat len, * x, * y, * z; 8.493 + CTMuint i; 8.494 + 8.495 + // Pointers to the basis axes (aBasisAxes is a 3x3 matrix) 8.496 + x = aBasisAxes; 8.497 + y = &aBasisAxes[3]; 8.498 + z = &aBasisAxes[6]; 8.499 + 8.500 + // Z = normal (must be unit length!) 8.501 + for(i = 0; i < 3; ++ i) 8.502 + z[i] = aNormal[i]; 8.503 + 8.504 + // Calculate a vector that is guaranteed to be orthogonal to the normal, non- 8.505 + // zero, and a continuous function of the normal (no discrete jumps): 8.506 + // X = (0,0,1) x normal + (1,0,0) x normal 8.507 + x[0] = -aNormal[1]; 8.508 + x[1] = aNormal[0] - aNormal[2]; 8.509 + x[2] = aNormal[1]; 8.510 + 8.511 + // Normalize the new X axis (note: |x[2]| = |x[0]|) 8.512 + len = sqrtf(2.0 * x[0] * x[0] + x[1] * x[1]); 8.513 + if(len > 1.0e-20f) 8.514 + { 8.515 + len = 1.0f / len; 8.516 + x[0] *= len; 8.517 + x[1] *= len; 8.518 + x[2] *= len; 8.519 + } 8.520 + 8.521 + // Let Y = Z x X (no normalization needed, since |Z| = |X| = 1) 8.522 + y[0] = z[1] * x[2] - z[2] * x[1]; 8.523 + y[1] = z[2] * x[0] - z[0] * x[2]; 8.524 + y[2] = z[0] * x[1] - z[1] * x[0]; 8.525 +} 8.526 + 8.527 +//----------------------------------------------------------------------------- 8.528 +// _ctmMakeNormalDeltas() - Convert the normals to a new coordinate system: 8.529 +// magnitude, phi, theta (relative to predicted smooth normals). 8.530 +//----------------------------------------------------------------------------- 8.531 +static CTMint _ctmMakeNormalDeltas(_CTMcontext * self, CTMint * aIntNormals, 8.532 + CTMfloat * aVertices, CTMuint * aIndices, _CTMsortvertex * aSortVertices) 8.533 +{ 8.534 + CTMuint i, j, oldIdx, intPhi; 8.535 + CTMfloat magn, phi, theta, scale, thetaScale; 8.536 + CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9]; 8.537 + 8.538 + // Allocate temporary memory for the nominal vertex normals 8.539 + smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount); 8.540 + if(!smoothNormals) 8.541 + { 8.542 + self->mError = CTM_OUT_OF_MEMORY; 8.543 + return CTM_FALSE; 8.544 + } 8.545 + 8.546 + // Calculate smooth normals (Note: aVertices and aIndices use the sorted 8.547 + // index space, so smoothNormals will too) 8.548 + _ctmCalcSmoothNormals(self, aVertices, aIndices, smoothNormals); 8.549 + 8.550 + // Normal scaling factor 8.551 + scale = 1.0f / self->mNormalPrecision; 8.552 + 8.553 + for(i = 0; i < self->mVertexCount; ++ i) 8.554 + { 8.555 + // Get old normal index (before vertex sorting) 8.556 + oldIdx = aSortVertices[i].mOriginalIndex; 8.557 + 8.558 + // Calculate normal magnitude (should always be 1.0 for unit length normals) 8.559 + magn = sqrtf(self->mNormals[oldIdx * 3] * self->mNormals[oldIdx * 3] + 8.560 + self->mNormals[oldIdx * 3 + 1] * self->mNormals[oldIdx * 3 + 1] + 8.561 + self->mNormals[oldIdx * 3 + 2] * self->mNormals[oldIdx * 3 + 2]); 8.562 + if(magn < 1e-10f) 8.563 + magn = 1.0f; 8.564 + 8.565 + // Invert magnitude if the normal is negative compared to the predicted 8.566 + // smooth normal 8.567 + if((smoothNormals[i * 3] * self->mNormals[oldIdx * 3] + 8.568 + smoothNormals[i * 3 + 1] * self->mNormals[oldIdx * 3 + 1] + 8.569 + smoothNormals[i * 3 + 2] * self->mNormals[oldIdx * 3 + 2]) < 0.0f) 8.570 + magn = -magn; 8.571 + 8.572 + // Store the magnitude in the first element of the three normal elements 8.573 + aIntNormals[i * 3] = (CTMint) floorf(scale * magn + 0.5f); 8.574 + 8.575 + // Normalize the normal (1 / magn) - and flip it if magn < 0 8.576 + magn = 1.0f / magn; 8.577 + for(j = 0; j < 3; ++ j) 8.578 + n[j] = self->mNormals[oldIdx * 3 + j] * magn; 8.579 + 8.580 + // Convert the normal to angular representation (phi, theta) in a coordinate 8.581 + // system where the nominal (smooth) normal is the Z-axis 8.582 + _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes); 8.583 + for(j = 0; j < 3; ++ j) 8.584 + n2[j] = basisAxes[j * 3] * n[0] + 8.585 + basisAxes[j * 3 + 1] * n[1] + 8.586 + basisAxes[j * 3 + 2] * n[2]; 8.587 + if(n2[2] >= 1.0f) 8.588 + phi = 0.0f; 8.589 + else 8.590 + phi = acosf(n2[2]); 8.591 + theta = atan2f(n2[1], n2[0]); 8.592 + 8.593 + // Round phi and theta (spherical coordinates) to integers. Note: We let the 8.594 + // theta resolution vary with the x/y circumference (roughly phi). 8.595 + intPhi = (CTMint) floorf(phi * (scale / (0.5f * PI)) + 0.5f); 8.596 + if(intPhi == 0) 8.597 + thetaScale = 0.0f; 8.598 + else if(intPhi <= 4) 8.599 + thetaScale = 2.0f / PI; 8.600 + else 8.601 + thetaScale = ((CTMfloat) intPhi) / (2.0f * PI); 8.602 + aIntNormals[i * 3 + 1] = intPhi; 8.603 + aIntNormals[i * 3 + 2] = (CTMint) floorf((theta + PI) * thetaScale + 0.5f); 8.604 + } 8.605 + 8.606 + // Free temporary resources 8.607 + free(smoothNormals); 8.608 + 8.609 + return CTM_TRUE; 8.610 +} 8.611 + 8.612 +//----------------------------------------------------------------------------- 8.613 +// _ctmRestoreNormals() - Convert the normals back to cartesian coordinates. 8.614 +//----------------------------------------------------------------------------- 8.615 +static CTMint _ctmRestoreNormals(_CTMcontext * self, CTMint * aIntNormals) 8.616 +{ 8.617 + CTMuint i, j, intPhi; 8.618 + CTMfloat magn, phi, theta, scale, thetaScale; 8.619 + CTMfloat * smoothNormals, n[3], n2[3], basisAxes[9]; 8.620 + 8.621 + // Allocate temporary memory for the nominal vertex normals 8.622 + smoothNormals = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * self->mVertexCount); 8.623 + if(!smoothNormals) 8.624 + { 8.625 + self->mError = CTM_OUT_OF_MEMORY; 8.626 + return CTM_FALSE; 8.627 + } 8.628 + 8.629 + // Calculate smooth normals (nominal normals) 8.630 + _ctmCalcSmoothNormals(self, self->mVertices, self->mIndices, smoothNormals); 8.631 + 8.632 + // Normal scaling factor 8.633 + scale = self->mNormalPrecision; 8.634 + 8.635 + for(i = 0; i < self->mVertexCount; ++ i) 8.636 + { 8.637 + // Get the normal magnitude from the first of the three normal elements 8.638 + magn = aIntNormals[i * 3] * scale; 8.639 + 8.640 + // Get phi and theta (spherical coordinates, relative to the smooth normal). 8.641 + intPhi = aIntNormals[i * 3 + 1]; 8.642 + phi = intPhi * (0.5f * PI) * scale; 8.643 + if(intPhi == 0) 8.644 + thetaScale = 0.0f; 8.645 + else if(intPhi <= 4) 8.646 + thetaScale = PI / 2.0f; 8.647 + else 8.648 + thetaScale = (2.0f * PI) / ((CTMfloat) intPhi); 8.649 + theta = aIntNormals[i * 3 + 2] * thetaScale - PI; 8.650 + 8.651 + // Convert the normal from the angular representation (phi, theta) back to 8.652 + // cartesian coordinates 8.653 + n2[0] = sinf(phi) * cosf(theta); 8.654 + n2[1] = sinf(phi) * sinf(theta); 8.655 + n2[2] = cosf(phi); 8.656 + _ctmMakeNormalCoordSys(&smoothNormals[i * 3], basisAxes); 8.657 + for(j = 0; j < 3; ++ j) 8.658 + n[j] = basisAxes[j] * n2[0] + 8.659 + basisAxes[3 + j] * n2[1] + 8.660 + basisAxes[6 + j] * n2[2]; 8.661 + 8.662 + // Apply normal magnitude, and output to the normals array 8.663 + for(j = 0; j < 3; ++ j) 8.664 + self->mNormals[i * 3 + j] = n[j] * magn; 8.665 + } 8.666 + 8.667 + // Free temporary resources 8.668 + free(smoothNormals); 8.669 + 8.670 + return CTM_TRUE; 8.671 +} 8.672 + 8.673 +//----------------------------------------------------------------------------- 8.674 +// _ctmMakeUVCoordDeltas() - Calculate various forms of derivatives in order 8.675 +// to reduce data entropy. 8.676 +//----------------------------------------------------------------------------- 8.677 +static void _ctmMakeUVCoordDeltas(_CTMcontext * self, _CTMfloatmap * aMap, 8.678 + CTMint * aIntUVCoords, _CTMsortvertex * aSortVertices) 8.679 +{ 8.680 + CTMuint i, oldIdx; 8.681 + CTMint u, v, prevU, prevV; 8.682 + CTMfloat scale; 8.683 + 8.684 + // UV coordinate scaling factor 8.685 + scale = 1.0f / aMap->mPrecision; 8.686 + 8.687 + prevU = prevV = 0; 8.688 + for(i = 0; i < self->mVertexCount; ++ i) 8.689 + { 8.690 + // Get old UV coordinate index (before vertex sorting) 8.691 + oldIdx = aSortVertices[i].mOriginalIndex; 8.692 + 8.693 + // Convert to fixed point 8.694 + u = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2] + 0.5f); 8.695 + v = (CTMint) floorf(scale * aMap->mValues[oldIdx * 2 + 1] + 0.5f); 8.696 + 8.697 + // Calculate delta and store it in the converted array. NOTE: Here we rely 8.698 + // on the fact that vertices are sorted, and usually close to each other, 8.699 + // which means that UV coordinates should also be close to each other... 8.700 + aIntUVCoords[i * 2] = u - prevU; 8.701 + aIntUVCoords[i * 2 + 1] = v - prevV; 8.702 + 8.703 + prevU = u; 8.704 + prevV = v; 8.705 + } 8.706 +} 8.707 + 8.708 +//----------------------------------------------------------------------------- 8.709 +// _ctmRestoreUVCoords() - Calculate inverse derivatives of the UV 8.710 +// coordinates. 8.711 +//----------------------------------------------------------------------------- 8.712 +static void _ctmRestoreUVCoords(_CTMcontext * self, _CTMfloatmap * aMap, 8.713 + CTMint * aIntUVCoords) 8.714 +{ 8.715 + CTMuint i; 8.716 + CTMint u, v, prevU, prevV; 8.717 + CTMfloat scale; 8.718 + 8.719 + // UV coordinate scaling factor 8.720 + scale = aMap->mPrecision; 8.721 + 8.722 + prevU = prevV = 0; 8.723 + for(i = 0; i < self->mVertexCount; ++ i) 8.724 + { 8.725 + // Calculate inverse delta 8.726 + u = aIntUVCoords[i * 2] + prevU; 8.727 + v = aIntUVCoords[i * 2 + 1] + prevV; 8.728 + 8.729 + // Convert to floating point 8.730 + aMap->mValues[i * 2] = (CTMfloat) u * scale; 8.731 + aMap->mValues[i * 2 + 1] = (CTMfloat) v * scale; 8.732 + 8.733 + prevU = u; 8.734 + prevV = v; 8.735 + } 8.736 +} 8.737 + 8.738 +//----------------------------------------------------------------------------- 8.739 +// _ctmMakeAttribDeltas() - Calculate various forms of derivatives in order 8.740 +// to reduce data entropy. 8.741 +//----------------------------------------------------------------------------- 8.742 +static void _ctmMakeAttribDeltas(_CTMcontext * self, _CTMfloatmap * aMap, 8.743 + CTMint * aIntAttribs, _CTMsortvertex * aSortVertices) 8.744 +{ 8.745 + CTMuint i, j, oldIdx; 8.746 + CTMint value[4], prev[4]; 8.747 + CTMfloat scale; 8.748 + 8.749 + // Attribute scaling factor 8.750 + scale = 1.0f / aMap->mPrecision; 8.751 + 8.752 + for(j = 0; j < 4; ++ j) 8.753 + prev[j] = 0; 8.754 + 8.755 + for(i = 0; i < self->mVertexCount; ++ i) 8.756 + { 8.757 + // Get old attribute index (before vertex sorting) 8.758 + oldIdx = aSortVertices[i].mOriginalIndex; 8.759 + 8.760 + // Convert to fixed point, and calculate delta and store it in the converted 8.761 + // array. NOTE: Here we rely on the fact that vertices are sorted, and 8.762 + // usually close to each other, which means that attributes should also 8.763 + // be close to each other (and we assume that they somehow vary slowly with 8.764 + // the geometry)... 8.765 + for(j = 0; j < 4; ++ j) 8.766 + { 8.767 + value[j] = (CTMint) floorf(scale * aMap->mValues[oldIdx * 4 + j] + 0.5f); 8.768 + aIntAttribs[i * 4 + j] = value[j] - prev[j]; 8.769 + prev[j] = value[j]; 8.770 + } 8.771 + } 8.772 +} 8.773 + 8.774 +//----------------------------------------------------------------------------- 8.775 +// _ctmRestoreAttribs() - Calculate inverse derivatives of the vertex 8.776 +// attributes. 8.777 +//----------------------------------------------------------------------------- 8.778 +static void _ctmRestoreAttribs(_CTMcontext * self, _CTMfloatmap * aMap, 8.779 + CTMint * aIntAttribs) 8.780 +{ 8.781 + CTMuint i, j; 8.782 + CTMint value[4], prev[4]; 8.783 + CTMfloat scale; 8.784 + 8.785 + // Attribute scaling factor 8.786 + scale = aMap->mPrecision; 8.787 + 8.788 + for(j = 0; j < 4; ++ j) 8.789 + prev[j] = 0; 8.790 + 8.791 + for(i = 0; i < self->mVertexCount; ++ i) 8.792 + { 8.793 + // Calculate inverse delta, and convert to floating point 8.794 + for(j = 0; j < 4; ++ j) 8.795 + { 8.796 + value[j] = aIntAttribs[i * 4 + j] + prev[j]; 8.797 + aMap->mValues[i * 4 + j] = (CTMfloat) value[j] * scale; 8.798 + prev[j] = value[j]; 8.799 + } 8.800 + } 8.801 +} 8.802 + 8.803 +//----------------------------------------------------------------------------- 8.804 +// _ctmCompressMesh_MG2() - Compress the mesh that is stored in the CTM 8.805 +// context, and write it the the output stream in the CTM context. 8.806 +//----------------------------------------------------------------------------- 8.807 +int _ctmCompressMesh_MG2(_CTMcontext * self) 8.808 +{ 8.809 + _CTMgrid grid; 8.810 + _CTMsortvertex * sortVertices; 8.811 + _CTMfloatmap * map; 8.812 + CTMuint * indices, * deltaIndices, * gridIndices; 8.813 + CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs; 8.814 + CTMfloat * restoredVertices; 8.815 + CTMuint i; 8.816 + 8.817 +#ifdef __DEBUG_ 8.818 + printf("COMPRESSION METHOD: MG2\n"); 8.819 +#endif 8.820 + 8.821 + // Setup 3D space subdivision grid 8.822 + _ctmSetupGrid(self, &grid); 8.823 + 8.824 + // Write MG2-specific header information to the stream 8.825 + _ctmStreamWrite(self, (void *) "MG2H", 4); 8.826 + _ctmStreamWriteFLOAT(self, self->mVertexPrecision); 8.827 + _ctmStreamWriteFLOAT(self, self->mNormalPrecision); 8.828 + _ctmStreamWriteFLOAT(self, grid.mMin[0]); 8.829 + _ctmStreamWriteFLOAT(self, grid.mMin[1]); 8.830 + _ctmStreamWriteFLOAT(self, grid.mMin[2]); 8.831 + _ctmStreamWriteFLOAT(self, grid.mMax[0]); 8.832 + _ctmStreamWriteFLOAT(self, grid.mMax[1]); 8.833 + _ctmStreamWriteFLOAT(self, grid.mMax[2]); 8.834 + _ctmStreamWriteUINT(self, grid.mDivision[0]); 8.835 + _ctmStreamWriteUINT(self, grid.mDivision[1]); 8.836 + _ctmStreamWriteUINT(self, grid.mDivision[2]); 8.837 + 8.838 + // Prepare (sort) vertices 8.839 + sortVertices = (_CTMsortvertex *) malloc(sizeof(_CTMsortvertex) * self->mVertexCount); 8.840 + if(!sortVertices) 8.841 + { 8.842 + self->mError = CTM_OUT_OF_MEMORY; 8.843 + return CTM_FALSE; 8.844 + } 8.845 + _ctmSortVertices(self, sortVertices, &grid); 8.846 + 8.847 + // Convert vertices to integers and calculate vertex deltas (entropy-reduction) 8.848 + intVertices = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount); 8.849 + if(!intVertices) 8.850 + { 8.851 + self->mError = CTM_OUT_OF_MEMORY; 8.852 + free((void *) sortVertices); 8.853 + return CTM_FALSE; 8.854 + } 8.855 + _ctmMakeVertexDeltas(self, intVertices, sortVertices, &grid); 8.856 + 8.857 + // Write vertices 8.858 +#ifdef __DEBUG_ 8.859 + printf("Vertices: "); 8.860 +#endif 8.861 + _ctmStreamWrite(self, (void *) "VERT", 4); 8.862 + if(!_ctmStreamWritePackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE)) 8.863 + { 8.864 + free((void *) intVertices); 8.865 + free((void *) sortVertices); 8.866 + return CTM_FALSE; 8.867 + } 8.868 + 8.869 + // Prepare grid indices (deltas) 8.870 + gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); 8.871 + if(!gridIndices) 8.872 + { 8.873 + self->mError = CTM_OUT_OF_MEMORY; 8.874 + free((void *) intVertices); 8.875 + free((void *) sortVertices); 8.876 + return CTM_FALSE; 8.877 + } 8.878 + gridIndices[0] = sortVertices[0].mGridIndex; 8.879 + for(i = 1; i < self->mVertexCount; ++ i) 8.880 + gridIndices[i] = sortVertices[i].mGridIndex - sortVertices[i - 1].mGridIndex; 8.881 + 8.882 + // Write grid indices 8.883 +#ifdef __DEBUG_ 8.884 + printf("Grid indices: "); 8.885 +#endif 8.886 + _ctmStreamWrite(self, (void *) "GIDX", 4); 8.887 + if(!_ctmStreamWritePackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE)) 8.888 + { 8.889 + free((void *) gridIndices); 8.890 + free((void *) intVertices); 8.891 + free((void *) sortVertices); 8.892 + return CTM_FALSE; 8.893 + } 8.894 + 8.895 + // Calculate the result of the compressed -> decompressed vertices, in order 8.896 + // to use the same vertex data for calculating nominal normals as the 8.897 + // decompression routine (i.e. compensate for the vertex error when 8.898 + // calculating the normals) 8.899 + restoredVertices = (CTMfloat *) malloc(sizeof(CTMfloat) * 3 * self->mVertexCount); 8.900 + if(!restoredVertices) 8.901 + { 8.902 + self->mError = CTM_OUT_OF_MEMORY; 8.903 + free((void *) gridIndices); 8.904 + free((void *) intVertices); 8.905 + free((void *) sortVertices); 8.906 + return CTM_FALSE; 8.907 + } 8.908 + for(i = 1; i < self->mVertexCount; ++ i) 8.909 + gridIndices[i] += gridIndices[i - 1]; 8.910 + _ctmRestoreVertices(self, intVertices, gridIndices, &grid, restoredVertices); 8.911 + 8.912 + // Free temporary resources 8.913 + free((void *) gridIndices); 8.914 + free((void *) intVertices); 8.915 + 8.916 + // Perpare (sort) indices 8.917 + indices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); 8.918 + if(!indices) 8.919 + { 8.920 + self->mError = CTM_OUT_OF_MEMORY; 8.921 + free((void *) restoredVertices); 8.922 + free((void *) sortVertices); 8.923 + return CTM_FALSE; 8.924 + } 8.925 + if(!_ctmReIndexIndices(self, sortVertices, indices)) 8.926 + { 8.927 + free((void *) indices); 8.928 + free((void *) restoredVertices); 8.929 + free((void *) sortVertices); 8.930 + return CTM_FALSE; 8.931 + } 8.932 + _ctmReArrangeTriangles(self, indices); 8.933 + 8.934 + // Calculate index deltas (entropy-reduction) 8.935 + deltaIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mTriangleCount * 3); 8.936 + if(!indices) 8.937 + { 8.938 + self->mError = CTM_OUT_OF_MEMORY; 8.939 + free((void *) indices); 8.940 + free((void *) restoredVertices); 8.941 + free((void *) sortVertices); 8.942 + return CTM_FALSE; 8.943 + } 8.944 + for(i = 0; i < self->mTriangleCount * 3; ++ i) 8.945 + deltaIndices[i] = indices[i]; 8.946 + _ctmMakeIndexDeltas(self, deltaIndices); 8.947 + 8.948 + // Write triangle indices 8.949 +#ifdef __DEBUG_ 8.950 + printf("Indices: "); 8.951 +#endif 8.952 + _ctmStreamWrite(self, (void *) "INDX", 4); 8.953 + if(!_ctmStreamWritePackedInts(self, (CTMint *) deltaIndices, self->mTriangleCount, 3, CTM_FALSE)) 8.954 + { 8.955 + free((void *) deltaIndices); 8.956 + free((void *) indices); 8.957 + free((void *) restoredVertices); 8.958 + free((void *) sortVertices); 8.959 + return CTM_FALSE; 8.960 + } 8.961 + 8.962 + // Free temporary data for the indices 8.963 + free((void *) deltaIndices); 8.964 + 8.965 + if(self->mNormals) 8.966 + { 8.967 + // Convert normals to integers and calculate deltas (entropy-reduction) 8.968 + intNormals = (CTMint *) malloc(sizeof(CTMint) * 3 * self->mVertexCount); 8.969 + if(!intNormals) 8.970 + { 8.971 + self->mError = CTM_OUT_OF_MEMORY; 8.972 + free((void *) indices); 8.973 + free((void *) restoredVertices); 8.974 + free((void *) sortVertices); 8.975 + return CTM_FALSE; 8.976 + } 8.977 + if(!_ctmMakeNormalDeltas(self, intNormals, restoredVertices, indices, sortVertices)) 8.978 + { 8.979 + free((void *) indices); 8.980 + free((void *) intNormals); 8.981 + free((void *) restoredVertices); 8.982 + free((void *) sortVertices); 8.983 + return CTM_FALSE; 8.984 + } 8.985 + 8.986 + // Write normals 8.987 +#ifdef __DEBUG_ 8.988 + printf("Normals: "); 8.989 +#endif 8.990 + _ctmStreamWrite(self, (void *) "NORM", 4); 8.991 + if(!_ctmStreamWritePackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE)) 8.992 + { 8.993 + free((void *) indices); 8.994 + free((void *) intNormals); 8.995 + free((void *) restoredVertices); 8.996 + free((void *) sortVertices); 8.997 + return CTM_FALSE; 8.998 + } 8.999 + 8.1000 + // Free temporary normal data 8.1001 + free((void *) intNormals); 8.1002 + } 8.1003 + 8.1004 + // Free restored indices and vertices 8.1005 + free((void *) indices); 8.1006 + free((void *) restoredVertices); 8.1007 + 8.1008 + // Write UV maps 8.1009 + map = self->mUVMaps; 8.1010 + while(map) 8.1011 + { 8.1012 + // Convert UV coordinates to integers and calculate deltas (entropy-reduction) 8.1013 + intUVCoords = (CTMint *) malloc(sizeof(CTMint) * 2 * self->mVertexCount); 8.1014 + if(!intUVCoords) 8.1015 + { 8.1016 + self->mError = CTM_OUT_OF_MEMORY; 8.1017 + free((void *) sortVertices); 8.1018 + return CTM_FALSE; 8.1019 + } 8.1020 + _ctmMakeUVCoordDeltas(self, map, intUVCoords, sortVertices); 8.1021 + 8.1022 + // Write UV coordinates 8.1023 +#ifdef __DEBUG_ 8.1024 + printf("Texture coordinates (%s): ", map->mName ? map->mName : "no name"); 8.1025 +#endif 8.1026 + _ctmStreamWrite(self, (void *) "TEXC", 4); 8.1027 + _ctmStreamWriteSTRING(self, map->mName); 8.1028 + _ctmStreamWriteSTRING(self, map->mFileName); 8.1029 + _ctmStreamWriteFLOAT(self, map->mPrecision); 8.1030 + if(!_ctmStreamWritePackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE)) 8.1031 + { 8.1032 + free((void *) intUVCoords); 8.1033 + free((void *) sortVertices); 8.1034 + return CTM_FALSE; 8.1035 + } 8.1036 + 8.1037 + // Free temporary UV coordinate data 8.1038 + free((void *) intUVCoords); 8.1039 + 8.1040 + map = map->mNext; 8.1041 + } 8.1042 + 8.1043 + // Write vertex attribute maps 8.1044 + map = self->mAttribMaps; 8.1045 + while(map) 8.1046 + { 8.1047 + // Convert vertex attributes to integers and calculate deltas (entropy-reduction) 8.1048 + intAttribs = (CTMint *) malloc(sizeof(CTMint) * 4 * self->mVertexCount); 8.1049 + if(!intAttribs) 8.1050 + { 8.1051 + self->mError = CTM_OUT_OF_MEMORY; 8.1052 + free((void *) sortVertices); 8.1053 + return CTM_FALSE; 8.1054 + } 8.1055 + _ctmMakeAttribDeltas(self, map, intAttribs, sortVertices); 8.1056 + 8.1057 + // Write vertex attributes 8.1058 +#ifdef __DEBUG_ 8.1059 + printf("Vertex attributes (%s): ", map->mName ? map->mName : "no name"); 8.1060 +#endif 8.1061 + _ctmStreamWrite(self, (void *) "ATTR", 4); 8.1062 + _ctmStreamWriteSTRING(self, map->mName); 8.1063 + _ctmStreamWriteFLOAT(self, map->mPrecision); 8.1064 + if(!_ctmStreamWritePackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE)) 8.1065 + { 8.1066 + free((void *) intAttribs); 8.1067 + free((void *) sortVertices); 8.1068 + return CTM_FALSE; 8.1069 + } 8.1070 + 8.1071 + // Free temporary vertex attribute data 8.1072 + free((void *) intAttribs); 8.1073 + 8.1074 + map = map->mNext; 8.1075 + } 8.1076 + 8.1077 + // Free temporary data 8.1078 + free((void *) sortVertices); 8.1079 + 8.1080 + return CTM_TRUE; 8.1081 +} 8.1082 + 8.1083 +//----------------------------------------------------------------------------- 8.1084 +// _ctmUncompressMesh_MG2() - Uncmpress the mesh from the input stream in the 8.1085 +// CTM context, and store the resulting mesh in the CTM context. 8.1086 +//----------------------------------------------------------------------------- 8.1087 +int _ctmUncompressMesh_MG2(_CTMcontext * self) 8.1088 +{ 8.1089 + CTMuint * gridIndices, i; 8.1090 + CTMint * intVertices, * intNormals, * intUVCoords, * intAttribs; 8.1091 + _CTMfloatmap * map; 8.1092 + _CTMgrid grid; 8.1093 + 8.1094 + // Read MG2-specific header information from the stream 8.1095 + if(_ctmStreamReadUINT(self) != FOURCC("MG2H")) 8.1096 + { 8.1097 + self->mError = CTM_BAD_FORMAT; 8.1098 + return CTM_FALSE; 8.1099 + } 8.1100 + self->mVertexPrecision = _ctmStreamReadFLOAT(self); 8.1101 + if(self->mVertexPrecision <= 0.0f) 8.1102 + { 8.1103 + self->mError = CTM_BAD_FORMAT; 8.1104 + return CTM_FALSE; 8.1105 + } 8.1106 + self->mNormalPrecision = _ctmStreamReadFLOAT(self); 8.1107 + if(self->mNormalPrecision <= 0.0f) 8.1108 + { 8.1109 + self->mError = CTM_BAD_FORMAT; 8.1110 + return CTM_FALSE; 8.1111 + } 8.1112 + grid.mMin[0] = _ctmStreamReadFLOAT(self); 8.1113 + grid.mMin[1] = _ctmStreamReadFLOAT(self); 8.1114 + grid.mMin[2] = _ctmStreamReadFLOAT(self); 8.1115 + grid.mMax[0] = _ctmStreamReadFLOAT(self); 8.1116 + grid.mMax[1] = _ctmStreamReadFLOAT(self); 8.1117 + grid.mMax[2] = _ctmStreamReadFLOAT(self); 8.1118 + if((grid.mMax[0] < grid.mMin[0]) || 8.1119 + (grid.mMax[1] < grid.mMin[1]) || 8.1120 + (grid.mMax[2] < grid.mMin[2])) 8.1121 + { 8.1122 + self->mError = CTM_BAD_FORMAT; 8.1123 + return CTM_FALSE; 8.1124 + } 8.1125 + grid.mDivision[0] = _ctmStreamReadUINT(self); 8.1126 + grid.mDivision[1] = _ctmStreamReadUINT(self); 8.1127 + grid.mDivision[2] = _ctmStreamReadUINT(self); 8.1128 + if((grid.mDivision[0] < 1) || (grid.mDivision[1] < 1) || (grid.mDivision[2] < 1)) 8.1129 + { 8.1130 + self->mError = CTM_BAD_FORMAT; 8.1131 + return CTM_FALSE; 8.1132 + } 8.1133 + 8.1134 + // Initialize 3D space subdivision grid 8.1135 + for(i = 0; i < 3; ++ i) 8.1136 + grid.mSize[i] = (grid.mMax[i] - grid.mMin[i]) / grid.mDivision[i]; 8.1137 + 8.1138 + // Read vertices 8.1139 + if(_ctmStreamReadUINT(self) != FOURCC("VERT")) 8.1140 + { 8.1141 + self->mError = CTM_BAD_FORMAT; 8.1142 + return CTM_FALSE; 8.1143 + } 8.1144 + intVertices = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3); 8.1145 + if(!intVertices) 8.1146 + { 8.1147 + self->mError = CTM_OUT_OF_MEMORY; 8.1148 + return CTM_FALSE; 8.1149 + } 8.1150 + if(!_ctmStreamReadPackedInts(self, intVertices, self->mVertexCount, 3, CTM_FALSE)) 8.1151 + { 8.1152 + free((void *) intVertices); 8.1153 + return CTM_FALSE; 8.1154 + } 8.1155 + 8.1156 + // Read grid indices 8.1157 + if(_ctmStreamReadUINT(self) != FOURCC("GIDX")) 8.1158 + { 8.1159 + free((void *) intVertices); 8.1160 + self->mError = CTM_BAD_FORMAT; 8.1161 + return CTM_FALSE; 8.1162 + } 8.1163 + gridIndices = (CTMuint *) malloc(sizeof(CTMuint) * self->mVertexCount); 8.1164 + if(!gridIndices) 8.1165 + { 8.1166 + self->mError = CTM_OUT_OF_MEMORY; 8.1167 + free((void *) intVertices); 8.1168 + return CTM_FALSE; 8.1169 + } 8.1170 + if(!_ctmStreamReadPackedInts(self, (CTMint *) gridIndices, self->mVertexCount, 1, CTM_FALSE)) 8.1171 + { 8.1172 + free((void *) gridIndices); 8.1173 + free((void *) intVertices); 8.1174 + return CTM_FALSE; 8.1175 + } 8.1176 + 8.1177 + // Restore grid indices (deltas) 8.1178 + for(i = 1; i < self->mVertexCount; ++ i) 8.1179 + gridIndices[i] += gridIndices[i - 1]; 8.1180 + 8.1181 + // Restore vertices 8.1182 + _ctmRestoreVertices(self, intVertices, gridIndices, &grid, self->mVertices); 8.1183 + 8.1184 + // Free temporary resources 8.1185 + free((void *) gridIndices); 8.1186 + free((void *) intVertices); 8.1187 + 8.1188 + // Read triangle indices 8.1189 + if(_ctmStreamReadUINT(self) != FOURCC("INDX")) 8.1190 + { 8.1191 + self->mError = CTM_BAD_FORMAT; 8.1192 + return CTM_FALSE; 8.1193 + } 8.1194 + if(!_ctmStreamReadPackedInts(self, (CTMint *) self->mIndices, self->mTriangleCount, 3, CTM_FALSE)) 8.1195 + return CTM_FALSE; 8.1196 + 8.1197 + // Restore indices 8.1198 + _ctmRestoreIndices(self, self->mIndices); 8.1199 + 8.1200 + // Check that all indices are within range 8.1201 + for(i = 0; i < (self->mTriangleCount * 3); ++ i) 8.1202 + { 8.1203 + if(self->mIndices[i] >= self->mVertexCount) 8.1204 + { 8.1205 + self->mError = CTM_INVALID_MESH; 8.1206 + return CTM_FALSE; 8.1207 + } 8.1208 + } 8.1209 + 8.1210 + // Read normals 8.1211 + if(self->mNormals) 8.1212 + { 8.1213 + intNormals = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 3); 8.1214 + if(!intNormals) 8.1215 + { 8.1216 + self->mError = CTM_OUT_OF_MEMORY; 8.1217 + return CTM_FALSE; 8.1218 + } 8.1219 + if(_ctmStreamReadUINT(self) != FOURCC("NORM")) 8.1220 + { 8.1221 + self->mError = CTM_BAD_FORMAT; 8.1222 + free((void *) intNormals); 8.1223 + return CTM_FALSE; 8.1224 + } 8.1225 + if(!_ctmStreamReadPackedInts(self, intNormals, self->mVertexCount, 3, CTM_FALSE)) 8.1226 + { 8.1227 + free((void *) intNormals); 8.1228 + return CTM_FALSE; 8.1229 + } 8.1230 + 8.1231 + // Restore normals 8.1232 + if(!_ctmRestoreNormals(self, intNormals)) 8.1233 + { 8.1234 + free((void *) intNormals); 8.1235 + return CTM_FALSE; 8.1236 + } 8.1237 + 8.1238 + // Free temporary normals data 8.1239 + free((void *) intNormals); 8.1240 + } 8.1241 + 8.1242 + // Read UV maps 8.1243 + map = self->mUVMaps; 8.1244 + while(map) 8.1245 + { 8.1246 + intUVCoords = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 2); 8.1247 + if(!intUVCoords) 8.1248 + { 8.1249 + self->mError = CTM_OUT_OF_MEMORY; 8.1250 + return CTM_FALSE; 8.1251 + } 8.1252 + if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) 8.1253 + { 8.1254 + self->mError = CTM_BAD_FORMAT; 8.1255 + free((void *) intUVCoords); 8.1256 + return CTM_FALSE; 8.1257 + } 8.1258 + _ctmStreamReadSTRING(self, &map->mName); 8.1259 + _ctmStreamReadSTRING(self, &map->mFileName); 8.1260 + map->mPrecision = _ctmStreamReadFLOAT(self); 8.1261 + if(map->mPrecision <= 0.0f) 8.1262 + { 8.1263 + self->mError = CTM_BAD_FORMAT; 8.1264 + free((void *) intUVCoords); 8.1265 + return CTM_FALSE; 8.1266 + } 8.1267 + if(!_ctmStreamReadPackedInts(self, intUVCoords, self->mVertexCount, 2, CTM_TRUE)) 8.1268 + { 8.1269 + free((void *) intUVCoords); 8.1270 + return CTM_FALSE; 8.1271 + } 8.1272 + 8.1273 + // Restore UV coordinates 8.1274 + _ctmRestoreUVCoords(self, map, intUVCoords); 8.1275 + 8.1276 + // Free temporary UV coordinate data 8.1277 + free((void *) intUVCoords); 8.1278 + 8.1279 + map = map->mNext; 8.1280 + } 8.1281 + 8.1282 + // Read vertex attribute maps 8.1283 + map = self->mAttribMaps; 8.1284 + while(map) 8.1285 + { 8.1286 + intAttribs = (CTMint *) malloc(sizeof(CTMint) * self->mVertexCount * 4); 8.1287 + if(!intAttribs) 8.1288 + { 8.1289 + self->mError = CTM_OUT_OF_MEMORY; 8.1290 + return CTM_FALSE; 8.1291 + } 8.1292 + if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) 8.1293 + { 8.1294 + self->mError = CTM_BAD_FORMAT; 8.1295 + free((void *) intAttribs); 8.1296 + return CTM_FALSE; 8.1297 + } 8.1298 + _ctmStreamReadSTRING(self, &map->mName); 8.1299 + map->mPrecision = _ctmStreamReadFLOAT(self); 8.1300 + if(map->mPrecision <= 0.0f) 8.1301 + { 8.1302 + self->mError = CTM_BAD_FORMAT; 8.1303 + free((void *) intAttribs); 8.1304 + return CTM_FALSE; 8.1305 + } 8.1306 + if(!_ctmStreamReadPackedInts(self, intAttribs, self->mVertexCount, 4, CTM_TRUE)) 8.1307 + { 8.1308 + free((void *) intAttribs); 8.1309 + return CTM_FALSE; 8.1310 + } 8.1311 + 8.1312 + // Restore vertex attributes 8.1313 + _ctmRestoreAttribs(self, map, intAttribs); 8.1314 + 8.1315 + // Free temporary vertex attribute data 8.1316 + free((void *) intAttribs); 8.1317 + 8.1318 + map = map->mNext; 8.1319 + } 8.1320 + 8.1321 + return CTM_TRUE; 8.1322 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/libs/openctm/compressRAW.c Thu Sep 26 04:47:05 2013 +0300 9.3 @@ -0,0 +1,181 @@ 9.4 +//----------------------------------------------------------------------------- 9.5 +// Product: OpenCTM 9.6 +// File: compressRAW.c 9.7 +// Description: Implementation of the RAW compression method. 9.8 +//----------------------------------------------------------------------------- 9.9 +// Copyright (c) 2009-2010 Marcus Geelnard 9.10 +// 9.11 +// This software is provided 'as-is', without any express or implied 9.12 +// warranty. In no event will the authors be held liable for any damages 9.13 +// arising from the use of this software. 9.14 +// 9.15 +// Permission is granted to anyone to use this software for any purpose, 9.16 +// including commercial applications, and to alter it and redistribute it 9.17 +// freely, subject to the following restrictions: 9.18 +// 9.19 +// 1. The origin of this software must not be misrepresented; you must not 9.20 +// claim that you wrote the original software. If you use this software 9.21 +// in a product, an acknowledgment in the product documentation would be 9.22 +// appreciated but is not required. 9.23 +// 9.24 +// 2. Altered source versions must be plainly marked as such, and must not 9.25 +// be misrepresented as being the original software. 9.26 +// 9.27 +// 3. This notice may not be removed or altered from any source 9.28 +// distribution. 9.29 +//----------------------------------------------------------------------------- 9.30 + 9.31 +#include "openctm.h" 9.32 +#include "internal.h" 9.33 + 9.34 +#ifdef __DEBUG_ 9.35 +#include <stdio.h> 9.36 +#endif 9.37 + 9.38 + 9.39 +//----------------------------------------------------------------------------- 9.40 +// _ctmCompressMesh_RAW() - Compress the mesh that is stored in the CTM 9.41 +// context using the RAW method, and write it the the output stream in the CTM 9.42 +// context. 9.43 +//----------------------------------------------------------------------------- 9.44 +int _ctmCompressMesh_RAW(_CTMcontext * self) 9.45 +{ 9.46 + CTMuint i; 9.47 + _CTMfloatmap * map; 9.48 + 9.49 +#ifdef __DEBUG_ 9.50 + printf("COMPRESSION METHOD: RAW\n"); 9.51 +#endif 9.52 + 9.53 + // Write triangle indices 9.54 +#ifdef __DEBUG_ 9.55 + printf("Inidices: %d bytes\n", (CTMuint)(self->mTriangleCount * 3 * sizeof(CTMuint))); 9.56 +#endif 9.57 + _ctmStreamWrite(self, (void *) "INDX", 4); 9.58 + for(i = 0; i < self->mTriangleCount * 3; ++ i) 9.59 + _ctmStreamWriteUINT(self, self->mIndices[i]); 9.60 + 9.61 + // Write vertices 9.62 +#ifdef __DEBUG_ 9.63 + printf("Vertices: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat))); 9.64 +#endif 9.65 + _ctmStreamWrite(self, (void *) "VERT", 4); 9.66 + for(i = 0; i < self->mVertexCount * 3; ++ i) 9.67 + _ctmStreamWriteFLOAT(self, self->mVertices[i]); 9.68 + 9.69 + // Write normals 9.70 + if(self->mNormals) 9.71 + { 9.72 +#ifdef __DEBUG_ 9.73 + printf("Normals: %d bytes\n", (CTMuint)(self->mVertexCount * 3 * sizeof(CTMfloat))); 9.74 +#endif 9.75 + _ctmStreamWrite(self, (void *) "NORM", 4); 9.76 + for(i = 0; i < self->mVertexCount * 3; ++ i) 9.77 + _ctmStreamWriteFLOAT(self, self->mNormals[i]); 9.78 + } 9.79 + 9.80 + // Write UV maps 9.81 + map = self->mUVMaps; 9.82 + while(map) 9.83 + { 9.84 +#ifdef __DEBUG_ 9.85 + printf("UV coordinates (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 2 * sizeof(CTMfloat))); 9.86 +#endif 9.87 + _ctmStreamWrite(self, (void *) "TEXC", 4); 9.88 + _ctmStreamWriteSTRING(self, map->mName); 9.89 + _ctmStreamWriteSTRING(self, map->mFileName); 9.90 + for(i = 0; i < self->mVertexCount * 2; ++ i) 9.91 + _ctmStreamWriteFLOAT(self, map->mValues[i]); 9.92 + map = map->mNext; 9.93 + } 9.94 + 9.95 + // Write attribute maps 9.96 + map = self->mAttribMaps; 9.97 + while(map) 9.98 + { 9.99 +#ifdef __DEBUG_ 9.100 + printf("Vertex attributes (%s): %d bytes\n", map->mName ? map->mName : "no name", (CTMuint)(self->mVertexCount * 4 * sizeof(CTMfloat))); 9.101 +#endif 9.102 + _ctmStreamWrite(self, (void *) "ATTR", 4); 9.103 + _ctmStreamWriteSTRING(self, map->mName); 9.104 + for(i = 0; i < self->mVertexCount * 4; ++ i) 9.105 + _ctmStreamWriteFLOAT(self, map->mValues[i]); 9.106 + map = map->mNext; 9.107 + } 9.108 + 9.109 + return 1; 9.110 +} 9.111 + 9.112 +//----------------------------------------------------------------------------- 9.113 +// _ctmUncompressMesh_RAW() - Uncmpress the mesh from the input stream in the 9.114 +// CTM context using the RAW method, and store the resulting mesh in the CTM 9.115 +// context. 9.116 +//----------------------------------------------------------------------------- 9.117 +int _ctmUncompressMesh_RAW(_CTMcontext * self) 9.118 +{ 9.119 + CTMuint i; 9.120 + _CTMfloatmap * map; 9.121 + 9.122 + // Read triangle indices 9.123 + if(_ctmStreamReadUINT(self) != FOURCC("INDX")) 9.124 + { 9.125 + self->mError = CTM_BAD_FORMAT; 9.126 + return 0; 9.127 + } 9.128 + for(i = 0; i < self->mTriangleCount * 3; ++ i) 9.129 + self->mIndices[i] = _ctmStreamReadUINT(self); 9.130 + 9.131 + // Read vertices 9.132 + if(_ctmStreamReadUINT(self) != FOURCC("VERT")) 9.133 + { 9.134 + self->mError = CTM_BAD_FORMAT; 9.135 + return 0; 9.136 + } 9.137 + for(i = 0; i < self->mVertexCount * 3; ++ i) 9.138 + self->mVertices[i] = _ctmStreamReadFLOAT(self); 9.139 + 9.140 + // Read normals 9.141 + if(self->mNormals) 9.142 + { 9.143 + if(_ctmStreamReadUINT(self) != FOURCC("NORM")) 9.144 + { 9.145 + self->mError = CTM_BAD_FORMAT; 9.146 + return 0; 9.147 + } 9.148 + for(i = 0; i < self->mVertexCount * 3; ++ i) 9.149 + self->mNormals[i] = _ctmStreamReadFLOAT(self); 9.150 + } 9.151 + 9.152 + // Read UV maps 9.153 + map = self->mUVMaps; 9.154 + while(map) 9.155 + { 9.156 + if(_ctmStreamReadUINT(self) != FOURCC("TEXC")) 9.157 + { 9.158 + self->mError = CTM_BAD_FORMAT; 9.159 + return 0; 9.160 + } 9.161 + _ctmStreamReadSTRING(self, &map->mName); 9.162 + _ctmStreamReadSTRING(self, &map->mFileName); 9.163 + for(i = 0; i < self->mVertexCount * 2; ++ i) 9.164 + map->mValues[i] = _ctmStreamReadFLOAT(self); 9.165 + map = map->mNext; 9.166 + } 9.167 + 9.168 + // Read attribute maps 9.169 + map = self->mAttribMaps; 9.170 + while(map) 9.171 + { 9.172 + if(_ctmStreamReadUINT(self) != FOURCC("ATTR")) 9.173 + { 9.174 + self->mError = CTM_BAD_FORMAT; 9.175 + return 0; 9.176 + } 9.177 + _ctmStreamReadSTRING(self, &map->mName); 9.178 + for(i = 0; i < self->mVertexCount * 4; ++ i) 9.179 + map->mValues[i] = _ctmStreamReadFLOAT(self); 9.180 + map = map->mNext; 9.181 + } 9.182 + 9.183 + return 1; 9.184 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/libs/openctm/internal.h Thu Sep 26 04:47:05 2013 +0300 10.3 @@ -0,0 +1,147 @@ 10.4 +//----------------------------------------------------------------------------- 10.5 +// Product: OpenCTM 10.6 +// File: internal.h 10.7 +// Description: Internal (private) declarations, types and function prototypes. 10.8 +//----------------------------------------------------------------------------- 10.9 +// Copyright (c) 2009-2010 Marcus Geelnard 10.10 +// 10.11 +// This software is provided 'as-is', without any express or implied 10.12 +// warranty. In no event will the authors be held liable for any damages 10.13 +// arising from the use of this software. 10.14 +// 10.15 +// Permission is granted to anyone to use this software for any purpose, 10.16 +// including commercial applications, and to alter it and redistribute it 10.17 +// freely, subject to the following restrictions: 10.18 +// 10.19 +// 1. The origin of this software must not be misrepresented; you must not 10.20 +// claim that you wrote the original software. If you use this software 10.21 +// in a product, an acknowledgment in the product documentation would be 10.22 +// appreciated but is not required. 10.23 +// 10.24 +// 2. Altered source versions must be plainly marked as such, and must not 10.25 +// be misrepresented as being the original software. 10.26 +// 10.27 +// 3. This notice may not be removed or altered from any source 10.28 +// distribution. 10.29 +//----------------------------------------------------------------------------- 10.30 + 10.31 +#ifndef __OPENCTM_INTERNAL_H_ 10.32 +#define __OPENCTM_INTERNAL_H_ 10.33 + 10.34 +//----------------------------------------------------------------------------- 10.35 +// Constants 10.36 +//----------------------------------------------------------------------------- 10.37 +// OpenCTM file format version (v5). 10.38 +#define _CTM_FORMAT_VERSION 0x00000005 10.39 + 10.40 +// Flags for the Mesh flags field of the file header 10.41 +#define _CTM_HAS_NORMALS_BIT 0x00000001 10.42 + 10.43 +//----------------------------------------------------------------------------- 10.44 +// _CTMfloatmap - Internal representation of a floating point based vertex map 10.45 +// (used for UV maps and attribute maps). 10.46 +//----------------------------------------------------------------------------- 10.47 +typedef struct _CTMfloatmap_struct _CTMfloatmap; 10.48 +struct _CTMfloatmap_struct { 10.49 + char * mName; // Unique name 10.50 + char * mFileName; // File name reference (used only for UV maps) 10.51 + CTMfloat mPrecision; // Precision for this map 10.52 + CTMfloat * mValues; // Attribute/UV coordinate values (per vertex) 10.53 + _CTMfloatmap * mNext; // Pointer to the next map in the list (linked list) 10.54 +}; 10.55 + 10.56 +//----------------------------------------------------------------------------- 10.57 +// _CTMcontext - Internal CTM context structure. 10.58 +//----------------------------------------------------------------------------- 10.59 +typedef struct { 10.60 + // Context mode (import or export) 10.61 + CTMenum mMode; 10.62 + 10.63 + // Vertices 10.64 + CTMfloat * mVertices; 10.65 + CTMuint mVertexCount; 10.66 + 10.67 + // Indices 10.68 + CTMuint * mIndices; 10.69 + CTMuint mTriangleCount; 10.70 + 10.71 + // Normals (optional) 10.72 + CTMfloat * mNormals; 10.73 + 10.74 + // Multiple sets of UV coordinate maps (optional) 10.75 + CTMuint mUVMapCount; 10.76 + _CTMfloatmap * mUVMaps; 10.77 + 10.78 + // Multiple sets of custom vertex attribute maps (optional) 10.79 + CTMuint mAttribMapCount; 10.80 + _CTMfloatmap * mAttribMaps; 10.81 + 10.82 + // Last error code 10.83 + CTMenum mError; 10.84 + 10.85 + // The selected compression method 10.86 + CTMenum mMethod; 10.87 + 10.88 + // The selected compression level 10.89 + CTMuint mCompressionLevel; 10.90 + 10.91 + // Vertex coordinate precision 10.92 + CTMfloat mVertexPrecision; 10.93 + 10.94 + // Normal precision (angular + magnitude) 10.95 + CTMfloat mNormalPrecision; 10.96 + 10.97 + // File comment 10.98 + char * mFileComment; 10.99 + 10.100 + // Read() function pointer 10.101 + CTMreadfn mReadFn; 10.102 + 10.103 + // Write() function pointer 10.104 + CTMwritefn mWriteFn; 10.105 + 10.106 + // User data (for stream read/write - usually the stream handle) 10.107 + void * mUserData; 10.108 +} _CTMcontext; 10.109 + 10.110 +//----------------------------------------------------------------------------- 10.111 +// Macros 10.112 +//----------------------------------------------------------------------------- 10.113 +#define FOURCC(str) (((CTMuint) str[0]) | (((CTMuint) str[1]) << 8) | \ 10.114 + (((CTMuint) str[2]) << 16) | (((CTMuint) str[3]) << 24)) 10.115 + 10.116 +//----------------------------------------------------------------------------- 10.117 +// Funcion prototypes for stream.c 10.118 +//----------------------------------------------------------------------------- 10.119 +CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount); 10.120 +CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount); 10.121 +CTMuint _ctmStreamReadUINT(_CTMcontext * self); 10.122 +void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue); 10.123 +CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self); 10.124 +void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue); 10.125 +void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue); 10.126 +void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue); 10.127 +int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts); 10.128 +int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData, CTMuint aCount, CTMuint aSize, CTMint aSignedInts); 10.129 +int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize); 10.130 +int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData, CTMuint aCount, CTMuint aSize); 10.131 + 10.132 +//----------------------------------------------------------------------------- 10.133 +// Funcion prototypes for compressRAW.c 10.134 +//----------------------------------------------------------------------------- 10.135 +int _ctmCompressMesh_RAW(_CTMcontext * self); 10.136 +int _ctmUncompressMesh_RAW(_CTMcontext * self); 10.137 + 10.138 +//----------------------------------------------------------------------------- 10.139 +// Funcion prototypes for compressMG1.c 10.140 +//----------------------------------------------------------------------------- 10.141 +int _ctmCompressMesh_MG1(_CTMcontext * self); 10.142 +int _ctmUncompressMesh_MG1(_CTMcontext * self); 10.143 + 10.144 +//----------------------------------------------------------------------------- 10.145 +// Funcion prototypes for compressMG2.c 10.146 +//----------------------------------------------------------------------------- 10.147 +int _ctmCompressMesh_MG2(_CTMcontext * self); 10.148 +int _ctmUncompressMesh_MG2(_CTMcontext * self); 10.149 + 10.150 +#endif // __OPENCTM_INTERNAL_H_
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/libs/openctm/liblzma/Alloc.c Thu Sep 26 04:47:05 2013 +0300 11.3 @@ -0,0 +1,127 @@ 11.4 +/* Alloc.c -- Memory allocation functions 11.5 +2008-09-24 11.6 +Igor Pavlov 11.7 +Public domain */ 11.8 + 11.9 +#ifdef _WIN32 11.10 +#include <windows.h> 11.11 +#endif 11.12 +#include <stdlib.h> 11.13 + 11.14 +#include "Alloc.h" 11.15 + 11.16 +/* #define _SZ_ALLOC_DEBUG */ 11.17 + 11.18 +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ 11.19 +#ifdef _SZ_ALLOC_DEBUG 11.20 +#include <stdio.h> 11.21 +int g_allocCount = 0; 11.22 +int g_allocCountMid = 0; 11.23 +int g_allocCountBig = 0; 11.24 +#endif 11.25 + 11.26 +void *MyAlloc(size_t size) 11.27 +{ 11.28 + if (size == 0) 11.29 + return 0; 11.30 + #ifdef _SZ_ALLOC_DEBUG 11.31 + { 11.32 + void *p = malloc(size); 11.33 + fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); 11.34 + return p; 11.35 + } 11.36 + #else 11.37 + return malloc(size); 11.38 + #endif 11.39 +} 11.40 + 11.41 +void MyFree(void *address) 11.42 +{ 11.43 + #ifdef _SZ_ALLOC_DEBUG 11.44 + if (address != 0) 11.45 + fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); 11.46 + #endif 11.47 + free(address); 11.48 +} 11.49 + 11.50 +#ifdef _WIN32 11.51 + 11.52 +void *MidAlloc(size_t size) 11.53 +{ 11.54 + if (size == 0) 11.55 + return 0; 11.56 + #ifdef _SZ_ALLOC_DEBUG 11.57 + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); 11.58 + #endif 11.59 + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); 11.60 +} 11.61 + 11.62 +void MidFree(void *address) 11.63 +{ 11.64 + #ifdef _SZ_ALLOC_DEBUG 11.65 + if (address != 0) 11.66 + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); 11.67 + #endif 11.68 + if (address == 0) 11.69 + return; 11.70 + VirtualFree(address, 0, MEM_RELEASE); 11.71 +} 11.72 + 11.73 +#ifndef MEM_LARGE_PAGES 11.74 +#undef _7ZIP_LARGE_PAGES 11.75 +#endif 11.76 + 11.77 +#ifdef _7ZIP_LARGE_PAGES 11.78 +SIZE_T g_LargePageSize = 0; 11.79 +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); 11.80 +#endif 11.81 + 11.82 +void SetLargePageSize() 11.83 +{ 11.84 + #ifdef _7ZIP_LARGE_PAGES 11.85 + SIZE_T size = 0; 11.86 + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) 11.87 + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); 11.88 + if (largePageMinimum == 0) 11.89 + return; 11.90 + size = largePageMinimum(); 11.91 + if (size == 0 || (size & (size - 1)) != 0) 11.92 + return; 11.93 + g_LargePageSize = size; 11.94 + #endif 11.95 +} 11.96 + 11.97 + 11.98 +void *BigAlloc(size_t size) 11.99 +{ 11.100 + if (size == 0) 11.101 + return 0; 11.102 + #ifdef _SZ_ALLOC_DEBUG 11.103 + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); 11.104 + #endif 11.105 + 11.106 + #ifdef _7ZIP_LARGE_PAGES 11.107 + if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) 11.108 + { 11.109 + void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), 11.110 + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); 11.111 + if (res != 0) 11.112 + return res; 11.113 + } 11.114 + #endif 11.115 + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); 11.116 +} 11.117 + 11.118 +void BigFree(void *address) 11.119 +{ 11.120 + #ifdef _SZ_ALLOC_DEBUG 11.121 + if (address != 0) 11.122 + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); 11.123 + #endif 11.124 + 11.125 + if (address == 0) 11.126 + return; 11.127 + VirtualFree(address, 0, MEM_RELEASE); 11.128 +} 11.129 + 11.130 +#endif
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/libs/openctm/liblzma/Alloc.h Thu Sep 26 04:47:05 2013 +0300 12.3 @@ -0,0 +1,34 @@ 12.4 +/* Alloc.h -- Memory allocation functions 12.5 +2008-03-13 12.6 +Igor Pavlov 12.7 +Public domain */ 12.8 + 12.9 +#ifndef __COMMON_ALLOC_H 12.10 +#define __COMMON_ALLOC_H 12.11 + 12.12 +#include <stddef.h> 12.13 + 12.14 +#include "NameMangle.h" 12.15 + 12.16 +void *MyAlloc(size_t size); 12.17 +void MyFree(void *address); 12.18 + 12.19 +#ifdef _WIN32 12.20 + 12.21 +void SetLargePageSize(); 12.22 + 12.23 +void *MidAlloc(size_t size); 12.24 +void MidFree(void *address); 12.25 +void *BigAlloc(size_t size); 12.26 +void BigFree(void *address); 12.27 + 12.28 +#else 12.29 + 12.30 +#define MidAlloc(size) MyAlloc(size) 12.31 +#define MidFree(address) MyFree(address) 12.32 +#define BigAlloc(size) MyAlloc(size) 12.33 +#define BigFree(address) MyFree(address) 12.34 + 12.35 +#endif 12.36 + 12.37 +#endif
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/libs/openctm/liblzma/LzFind.c Thu Sep 26 04:47:05 2013 +0300 13.3 @@ -0,0 +1,751 @@ 13.4 +/* LzFind.c -- Match finder for LZ algorithms 13.5 +2008-10-04 : Igor Pavlov : Public domain */ 13.6 + 13.7 +#include <string.h> 13.8 + 13.9 +#include "LzFind.h" 13.10 +#include "LzHash.h" 13.11 + 13.12 +#define kEmptyHashValue 0 13.13 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) 13.14 +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ 13.15 +#define kNormalizeMask (~(kNormalizeStepMin - 1)) 13.16 +#define kMaxHistorySize ((UInt32)3 << 30) 13.17 + 13.18 +#define kStartMaxLen 3 13.19 + 13.20 +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) 13.21 +{ 13.22 + if (!p->directInput) 13.23 + { 13.24 + alloc->Free(alloc, p->bufferBase); 13.25 + p->bufferBase = 0; 13.26 + } 13.27 +} 13.28 + 13.29 +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ 13.30 + 13.31 +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) 13.32 +{ 13.33 + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; 13.34 + if (p->directInput) 13.35 + { 13.36 + p->blockSize = blockSize; 13.37 + return 1; 13.38 + } 13.39 + if (p->bufferBase == 0 || p->blockSize != blockSize) 13.40 + { 13.41 + LzInWindow_Free(p, alloc); 13.42 + p->blockSize = blockSize; 13.43 + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); 13.44 + } 13.45 + return (p->bufferBase != 0); 13.46 +} 13.47 + 13.48 +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } 13.49 +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } 13.50 + 13.51 +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } 13.52 + 13.53 +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) 13.54 +{ 13.55 + p->posLimit -= subValue; 13.56 + p->pos -= subValue; 13.57 + p->streamPos -= subValue; 13.58 +} 13.59 + 13.60 +static void MatchFinder_ReadBlock(CMatchFinder *p) 13.61 +{ 13.62 + if (p->streamEndWasReached || p->result != SZ_OK) 13.63 + return; 13.64 + for (;;) 13.65 + { 13.66 + Byte *dest = p->buffer + (p->streamPos - p->pos); 13.67 + size_t size = (p->bufferBase + p->blockSize - dest); 13.68 + if (size == 0) 13.69 + return; 13.70 + p->result = p->stream->Read(p->stream, dest, &size); 13.71 + if (p->result != SZ_OK) 13.72 + return; 13.73 + if (size == 0) 13.74 + { 13.75 + p->streamEndWasReached = 1; 13.76 + return; 13.77 + } 13.78 + p->streamPos += (UInt32)size; 13.79 + if (p->streamPos - p->pos > p->keepSizeAfter) 13.80 + return; 13.81 + } 13.82 +} 13.83 + 13.84 +void MatchFinder_MoveBlock(CMatchFinder *p) 13.85 +{ 13.86 + memmove(p->bufferBase, 13.87 + p->buffer - p->keepSizeBefore, 13.88 + (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); 13.89 + p->buffer = p->bufferBase + p->keepSizeBefore; 13.90 +} 13.91 + 13.92 +int MatchFinder_NeedMove(CMatchFinder *p) 13.93 +{ 13.94 + /* if (p->streamEndWasReached) return 0; */ 13.95 + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); 13.96 +} 13.97 + 13.98 +void MatchFinder_ReadIfRequired(CMatchFinder *p) 13.99 +{ 13.100 + if (p->streamEndWasReached) 13.101 + return; 13.102 + if (p->keepSizeAfter >= p->streamPos - p->pos) 13.103 + MatchFinder_ReadBlock(p); 13.104 +} 13.105 + 13.106 +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) 13.107 +{ 13.108 + if (MatchFinder_NeedMove(p)) 13.109 + MatchFinder_MoveBlock(p); 13.110 + MatchFinder_ReadBlock(p); 13.111 +} 13.112 + 13.113 +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) 13.114 +{ 13.115 + p->cutValue = 32; 13.116 + p->btMode = 1; 13.117 + p->numHashBytes = 4; 13.118 + /* p->skipModeBits = 0; */ 13.119 + p->directInput = 0; 13.120 + p->bigHash = 0; 13.121 +} 13.122 + 13.123 +#define kCrcPoly 0xEDB88320 13.124 + 13.125 +void MatchFinder_Construct(CMatchFinder *p) 13.126 +{ 13.127 + UInt32 i; 13.128 + p->bufferBase = 0; 13.129 + p->directInput = 0; 13.130 + p->hash = 0; 13.131 + MatchFinder_SetDefaultSettings(p); 13.132 + 13.133 + for (i = 0; i < 256; i++) 13.134 + { 13.135 + UInt32 r = i; 13.136 + int j; 13.137 + for (j = 0; j < 8; j++) 13.138 + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); 13.139 + p->crc[i] = r; 13.140 + } 13.141 +} 13.142 + 13.143 +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) 13.144 +{ 13.145 + alloc->Free(alloc, p->hash); 13.146 + p->hash = 0; 13.147 +} 13.148 + 13.149 +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) 13.150 +{ 13.151 + MatchFinder_FreeThisClassMemory(p, alloc); 13.152 + LzInWindow_Free(p, alloc); 13.153 +} 13.154 + 13.155 +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) 13.156 +{ 13.157 + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); 13.158 + if (sizeInBytes / sizeof(CLzRef) != num) 13.159 + return 0; 13.160 + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); 13.161 +} 13.162 + 13.163 +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, 13.164 + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, 13.165 + ISzAlloc *alloc) 13.166 +{ 13.167 + UInt32 sizeReserv; 13.168 + if (historySize > kMaxHistorySize) 13.169 + { 13.170 + MatchFinder_Free(p, alloc); 13.171 + return 0; 13.172 + } 13.173 + sizeReserv = historySize >> 1; 13.174 + if (historySize > ((UInt32)2 << 30)) 13.175 + sizeReserv = historySize >> 2; 13.176 + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); 13.177 + 13.178 + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; 13.179 + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; 13.180 + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ 13.181 + if (LzInWindow_Create(p, sizeReserv, alloc)) 13.182 + { 13.183 + UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1; 13.184 + UInt32 hs; 13.185 + p->matchMaxLen = matchMaxLen; 13.186 + { 13.187 + p->fixedHashSize = 0; 13.188 + if (p->numHashBytes == 2) 13.189 + hs = (1 << 16) - 1; 13.190 + else 13.191 + { 13.192 + hs = historySize - 1; 13.193 + hs |= (hs >> 1); 13.194 + hs |= (hs >> 2); 13.195 + hs |= (hs >> 4); 13.196 + hs |= (hs >> 8); 13.197 + hs >>= 1; 13.198 + /* hs >>= p->skipModeBits; */ 13.199 + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ 13.200 + if (hs > (1 << 24)) 13.201 + { 13.202 + if (p->numHashBytes == 3) 13.203 + hs = (1 << 24) - 1; 13.204 + else 13.205 + hs >>= 1; 13.206 + } 13.207 + } 13.208 + p->hashMask = hs; 13.209 + hs++; 13.210 + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; 13.211 + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; 13.212 + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; 13.213 + hs += p->fixedHashSize; 13.214 + } 13.215 + 13.216 + { 13.217 + UInt32 prevSize = p->hashSizeSum + p->numSons; 13.218 + UInt32 newSize; 13.219 + p->historySize = historySize; 13.220 + p->hashSizeSum = hs; 13.221 + p->cyclicBufferSize = newCyclicBufferSize; 13.222 + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); 13.223 + newSize = p->hashSizeSum + p->numSons; 13.224 + if (p->hash != 0 && prevSize == newSize) 13.225 + return 1; 13.226 + MatchFinder_FreeThisClassMemory(p, alloc); 13.227 + p->hash = AllocRefs(newSize, alloc); 13.228 + if (p->hash != 0) 13.229 + { 13.230 + p->son = p->hash + p->hashSizeSum; 13.231 + return 1; 13.232 + } 13.233 + } 13.234 + } 13.235 + MatchFinder_Free(p, alloc); 13.236 + return 0; 13.237 +} 13.238 + 13.239 +static void MatchFinder_SetLimits(CMatchFinder *p) 13.240 +{ 13.241 + UInt32 limit = kMaxValForNormalize - p->pos; 13.242 + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; 13.243 + if (limit2 < limit) 13.244 + limit = limit2; 13.245 + limit2 = p->streamPos - p->pos; 13.246 + if (limit2 <= p->keepSizeAfter) 13.247 + { 13.248 + if (limit2 > 0) 13.249 + limit2 = 1; 13.250 + } 13.251 + else 13.252 + limit2 -= p->keepSizeAfter; 13.253 + if (limit2 < limit) 13.254 + limit = limit2; 13.255 + { 13.256 + UInt32 lenLimit = p->streamPos - p->pos; 13.257 + if (lenLimit > p->matchMaxLen) 13.258 + lenLimit = p->matchMaxLen; 13.259 + p->lenLimit = lenLimit; 13.260 + } 13.261 + p->posLimit = p->pos + limit; 13.262 +} 13.263 + 13.264 +void MatchFinder_Init(CMatchFinder *p) 13.265 +{ 13.266 + UInt32 i; 13.267 + for (i = 0; i < p->hashSizeSum; i++) 13.268 + p->hash[i] = kEmptyHashValue; 13.269 + p->cyclicBufferPos = 0; 13.270 + p->buffer = p->bufferBase; 13.271 + p->pos = p->streamPos = p->cyclicBufferSize; 13.272 + p->result = SZ_OK; 13.273 + p->streamEndWasReached = 0; 13.274 + MatchFinder_ReadBlock(p); 13.275 + MatchFinder_SetLimits(p); 13.276 +} 13.277 + 13.278 +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) 13.279 +{ 13.280 + return (p->pos - p->historySize - 1) & kNormalizeMask; 13.281 +} 13.282 + 13.283 +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) 13.284 +{ 13.285 + UInt32 i; 13.286 + for (i = 0; i < numItems; i++) 13.287 + { 13.288 + UInt32 value = items[i]; 13.289 + if (value <= subValue) 13.290 + value = kEmptyHashValue; 13.291 + else 13.292 + value -= subValue; 13.293 + items[i] = value; 13.294 + } 13.295 +} 13.296 + 13.297 +static void MatchFinder_Normalize(CMatchFinder *p) 13.298 +{ 13.299 + UInt32 subValue = MatchFinder_GetSubValue(p); 13.300 + MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); 13.301 + MatchFinder_ReduceOffsets(p, subValue); 13.302 +} 13.303 + 13.304 +static void MatchFinder_CheckLimits(CMatchFinder *p) 13.305 +{ 13.306 + if (p->pos == kMaxValForNormalize) 13.307 + MatchFinder_Normalize(p); 13.308 + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) 13.309 + MatchFinder_CheckAndMoveAndRead(p); 13.310 + if (p->cyclicBufferPos == p->cyclicBufferSize) 13.311 + p->cyclicBufferPos = 0; 13.312 + MatchFinder_SetLimits(p); 13.313 +} 13.314 + 13.315 +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 13.316 + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, 13.317 + UInt32 *distances, UInt32 maxLen) 13.318 +{ 13.319 + son[_cyclicBufferPos] = curMatch; 13.320 + for (;;) 13.321 + { 13.322 + UInt32 delta = pos - curMatch; 13.323 + if (cutValue-- == 0 || delta >= _cyclicBufferSize) 13.324 + return distances; 13.325 + { 13.326 + const Byte *pb = cur - delta; 13.327 + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; 13.328 + if (pb[maxLen] == cur[maxLen] && *pb == *cur) 13.329 + { 13.330 + UInt32 len = 0; 13.331 + while (++len != lenLimit) 13.332 + if (pb[len] != cur[len]) 13.333 + break; 13.334 + if (maxLen < len) 13.335 + { 13.336 + *distances++ = maxLen = len; 13.337 + *distances++ = delta - 1; 13.338 + if (len == lenLimit) 13.339 + return distances; 13.340 + } 13.341 + } 13.342 + } 13.343 + } 13.344 +} 13.345 + 13.346 +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 13.347 + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, 13.348 + UInt32 *distances, UInt32 maxLen) 13.349 +{ 13.350 + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; 13.351 + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); 13.352 + UInt32 len0 = 0, len1 = 0; 13.353 + for (;;) 13.354 + { 13.355 + UInt32 delta = pos - curMatch; 13.356 + if (cutValue-- == 0 || delta >= _cyclicBufferSize) 13.357 + { 13.358 + *ptr0 = *ptr1 = kEmptyHashValue; 13.359 + return distances; 13.360 + } 13.361 + { 13.362 + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); 13.363 + const Byte *pb = cur - delta; 13.364 + UInt32 len = (len0 < len1 ? len0 : len1); 13.365 + if (pb[len] == cur[len]) 13.366 + { 13.367 + if (++len != lenLimit && pb[len] == cur[len]) 13.368 + while (++len != lenLimit) 13.369 + if (pb[len] != cur[len]) 13.370 + break; 13.371 + if (maxLen < len) 13.372 + { 13.373 + *distances++ = maxLen = len; 13.374 + *distances++ = delta - 1; 13.375 + if (len == lenLimit) 13.376 + { 13.377 + *ptr1 = pair[0]; 13.378 + *ptr0 = pair[1]; 13.379 + return distances; 13.380 + } 13.381 + } 13.382 + } 13.383 + if (pb[len] < cur[len]) 13.384 + { 13.385 + *ptr1 = curMatch; 13.386 + ptr1 = pair + 1; 13.387 + curMatch = *ptr1; 13.388 + len1 = len; 13.389 + } 13.390 + else 13.391 + { 13.392 + *ptr0 = curMatch; 13.393 + ptr0 = pair; 13.394 + curMatch = *ptr0; 13.395 + len0 = len; 13.396 + } 13.397 + } 13.398 + } 13.399 +} 13.400 + 13.401 +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, 13.402 + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) 13.403 +{ 13.404 + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; 13.405 + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); 13.406 + UInt32 len0 = 0, len1 = 0; 13.407 + for (;;) 13.408 + { 13.409 + UInt32 delta = pos - curMatch; 13.410 + if (cutValue-- == 0 || delta >= _cyclicBufferSize) 13.411 + { 13.412 + *ptr0 = *ptr1 = kEmptyHashValue; 13.413 + return; 13.414 + } 13.415 + { 13.416 + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); 13.417 + const Byte *pb = cur - delta; 13.418 + UInt32 len = (len0 < len1 ? len0 : len1); 13.419 + if (pb[len] == cur[len]) 13.420 + { 13.421 + while (++len != lenLimit) 13.422 + if (pb[len] != cur[len]) 13.423 + break; 13.424 + { 13.425 + if (len == lenLimit) 13.426 + { 13.427 + *ptr1 = pair[0]; 13.428 + *ptr0 = pair[1]; 13.429 + return; 13.430 + } 13.431 + } 13.432 + } 13.433 + if (pb[len] < cur[len]) 13.434 + { 13.435 + *ptr1 = curMatch; 13.436 + ptr1 = pair + 1; 13.437 + curMatch = *ptr1; 13.438 + len1 = len; 13.439 + } 13.440 + else 13.441 + { 13.442 + *ptr0 = curMatch; 13.443 + ptr0 = pair; 13.444 + curMatch = *ptr0; 13.445 + len0 = len; 13.446 + } 13.447 + } 13.448 + } 13.449 +} 13.450 + 13.451 +#define MOVE_POS \ 13.452 + ++p->cyclicBufferPos; \ 13.453 + p->buffer++; \ 13.454 + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); 13.455 + 13.456 +#define MOVE_POS_RET MOVE_POS return offset; 13.457 + 13.458 +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } 13.459 + 13.460 +#define GET_MATCHES_HEADER2(minLen, ret_op) \ 13.461 + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ 13.462 + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ 13.463 + cur = p->buffer; 13.464 + 13.465 +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) 13.466 +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) 13.467 + 13.468 +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue 13.469 + 13.470 +#define GET_MATCHES_FOOTER(offset, maxLen) \ 13.471 + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ 13.472 + distances + offset, maxLen) - distances); MOVE_POS_RET; 13.473 + 13.474 +#define SKIP_FOOTER \ 13.475 + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; 13.476 + 13.477 +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 13.478 +{ 13.479 + UInt32 offset; 13.480 + GET_MATCHES_HEADER(2) 13.481 + HASH2_CALC; 13.482 + curMatch = p->hash[hashValue]; 13.483 + p->hash[hashValue] = p->pos; 13.484 + offset = 0; 13.485 + GET_MATCHES_FOOTER(offset, 1) 13.486 +} 13.487 + 13.488 +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 13.489 +{ 13.490 + UInt32 offset; 13.491 + GET_MATCHES_HEADER(3) 13.492 + HASH_ZIP_CALC; 13.493 + curMatch = p->hash[hashValue]; 13.494 + p->hash[hashValue] = p->pos; 13.495 + offset = 0; 13.496 + GET_MATCHES_FOOTER(offset, 2) 13.497 +} 13.498 + 13.499 +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 13.500 +{ 13.501 + UInt32 hash2Value, delta2, maxLen, offset; 13.502 + GET_MATCHES_HEADER(3) 13.503 + 13.504 + HASH3_CALC; 13.505 + 13.506 + delta2 = p->pos - p->hash[hash2Value]; 13.507 + curMatch = p->hash[kFix3HashSize + hashValue]; 13.508 + 13.509 + p->hash[hash2Value] = 13.510 + p->hash[kFix3HashSize + hashValue] = p->pos; 13.511 + 13.512 + 13.513 + maxLen = 2; 13.514 + offset = 0; 13.515 + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) 13.516 + { 13.517 + for (; maxLen != lenLimit; maxLen++) 13.518 + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) 13.519 + break; 13.520 + distances[0] = maxLen; 13.521 + distances[1] = delta2 - 1; 13.522 + offset = 2; 13.523 + if (maxLen == lenLimit) 13.524 + { 13.525 + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); 13.526 + MOVE_POS_RET; 13.527 + } 13.528 + } 13.529 + GET_MATCHES_FOOTER(offset, maxLen) 13.530 +} 13.531 + 13.532 +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 13.533 +{ 13.534 + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; 13.535 + GET_MATCHES_HEADER(4) 13.536 + 13.537 + HASH4_CALC; 13.538 + 13.539 + delta2 = p->pos - p->hash[ hash2Value]; 13.540 + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; 13.541 + curMatch = p->hash[kFix4HashSize + hashValue]; 13.542 + 13.543 + p->hash[ hash2Value] = 13.544 + p->hash[kFix3HashSize + hash3Value] = 13.545 + p->hash[kFix4HashSize + hashValue] = p->pos; 13.546 + 13.547 + maxLen = 1; 13.548 + offset = 0; 13.549 + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) 13.550 + { 13.551 + distances[0] = maxLen = 2; 13.552 + distances[1] = delta2 - 1; 13.553 + offset = 2; 13.554 + } 13.555 + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) 13.556 + { 13.557 + maxLen = 3; 13.558 + distances[offset + 1] = delta3 - 1; 13.559 + offset += 2; 13.560 + delta2 = delta3; 13.561 + } 13.562 + if (offset != 0) 13.563 + { 13.564 + for (; maxLen != lenLimit; maxLen++) 13.565 + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) 13.566 + break; 13.567 + distances[offset - 2] = maxLen; 13.568 + if (maxLen == lenLimit) 13.569 + { 13.570 + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); 13.571 + MOVE_POS_RET; 13.572 + } 13.573 + } 13.574 + if (maxLen < 3) 13.575 + maxLen = 3; 13.576 + GET_MATCHES_FOOTER(offset, maxLen) 13.577 +} 13.578 + 13.579 +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 13.580 +{ 13.581 + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; 13.582 + GET_MATCHES_HEADER(4) 13.583 + 13.584 + HASH4_CALC; 13.585 + 13.586 + delta2 = p->pos - p->hash[ hash2Value]; 13.587 + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; 13.588 + curMatch = p->hash[kFix4HashSize + hashValue]; 13.589 + 13.590 + p->hash[ hash2Value] = 13.591 + p->hash[kFix3HashSize + hash3Value] = 13.592 + p->hash[kFix4HashSize + hashValue] = p->pos; 13.593 + 13.594 + maxLen = 1; 13.595 + offset = 0; 13.596 + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) 13.597 + { 13.598 + distances[0] = maxLen = 2; 13.599 + distances[1] = delta2 - 1; 13.600 + offset = 2; 13.601 + } 13.602 + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) 13.603 + { 13.604 + maxLen = 3; 13.605 + distances[offset + 1] = delta3 - 1; 13.606 + offset += 2; 13.607 + delta2 = delta3; 13.608 + } 13.609 + if (offset != 0) 13.610 + { 13.611 + for (; maxLen != lenLimit; maxLen++) 13.612 + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) 13.613 + break; 13.614 + distances[offset - 2] = maxLen; 13.615 + if (maxLen == lenLimit) 13.616 + { 13.617 + p->son[p->cyclicBufferPos] = curMatch; 13.618 + MOVE_POS_RET; 13.619 + } 13.620 + } 13.621 + if (maxLen < 3) 13.622 + maxLen = 3; 13.623 + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), 13.624 + distances + offset, maxLen) - (distances)); 13.625 + MOVE_POS_RET 13.626 +} 13.627 + 13.628 +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) 13.629 +{ 13.630 + UInt32 offset; 13.631 + GET_MATCHES_HEADER(3) 13.632 + HASH_ZIP_CALC; 13.633 + curMatch = p->hash[hashValue]; 13.634 + p->hash[hashValue] = p->pos; 13.635 + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), 13.636 + distances, 2) - (distances)); 13.637 + MOVE_POS_RET 13.638 +} 13.639 + 13.640 +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 13.641 +{ 13.642 + do 13.643 + { 13.644 + SKIP_HEADER(2) 13.645 + HASH2_CALC; 13.646 + curMatch = p->hash[hashValue]; 13.647 + p->hash[hashValue] = p->pos; 13.648 + SKIP_FOOTER 13.649 + } 13.650 + while (--num != 0); 13.651 +} 13.652 + 13.653 +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 13.654 +{ 13.655 + do 13.656 + { 13.657 + SKIP_HEADER(3) 13.658 + HASH_ZIP_CALC; 13.659 + curMatch = p->hash[hashValue]; 13.660 + p->hash[hashValue] = p->pos; 13.661 + SKIP_FOOTER 13.662 + } 13.663 + while (--num != 0); 13.664 +} 13.665 + 13.666 +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 13.667 +{ 13.668 + do 13.669 + { 13.670 + UInt32 hash2Value; 13.671 + SKIP_HEADER(3) 13.672 + HASH3_CALC; 13.673 + curMatch = p->hash[kFix3HashSize + hashValue]; 13.674 + p->hash[hash2Value] = 13.675 + p->hash[kFix3HashSize + hashValue] = p->pos; 13.676 + SKIP_FOOTER 13.677 + } 13.678 + while (--num != 0); 13.679 +} 13.680 + 13.681 +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 13.682 +{ 13.683 + do 13.684 + { 13.685 + UInt32 hash2Value, hash3Value; 13.686 + SKIP_HEADER(4) 13.687 + HASH4_CALC; 13.688 + curMatch = p->hash[kFix4HashSize + hashValue]; 13.689 + p->hash[ hash2Value] = 13.690 + p->hash[kFix3HashSize + hash3Value] = p->pos; 13.691 + p->hash[kFix4HashSize + hashValue] = p->pos; 13.692 + SKIP_FOOTER 13.693 + } 13.694 + while (--num != 0); 13.695 +} 13.696 + 13.697 +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 13.698 +{ 13.699 + do 13.700 + { 13.701 + UInt32 hash2Value, hash3Value; 13.702 + SKIP_HEADER(4) 13.703 + HASH4_CALC; 13.704 + curMatch = p->hash[kFix4HashSize + hashValue]; 13.705 + p->hash[ hash2Value] = 13.706 + p->hash[kFix3HashSize + hash3Value] = 13.707 + p->hash[kFix4HashSize + hashValue] = p->pos; 13.708 + p->son[p->cyclicBufferPos] = curMatch; 13.709 + MOVE_POS 13.710 + } 13.711 + while (--num != 0); 13.712 +} 13.713 + 13.714 +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) 13.715 +{ 13.716 + do 13.717 + { 13.718 + SKIP_HEADER(3) 13.719 + HASH_ZIP_CALC; 13.720 + curMatch = p->hash[hashValue]; 13.721 + p->hash[hashValue] = p->pos; 13.722 + p->son[p->cyclicBufferPos] = curMatch; 13.723 + MOVE_POS 13.724 + } 13.725 + while (--num != 0); 13.726 +} 13.727 + 13.728 +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) 13.729 +{ 13.730 + vTable->Init = (Mf_Init_Func)MatchFinder_Init; 13.731 + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; 13.732 + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; 13.733 + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; 13.734 + if (!p->btMode) 13.735 + { 13.736 + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; 13.737 + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; 13.738 + } 13.739 + else if (p->numHashBytes == 2) 13.740 + { 13.741 + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; 13.742 + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; 13.743 + } 13.744 + else if (p->numHashBytes == 3) 13.745 + { 13.746 + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; 13.747 + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; 13.748 + } 13.749 + else 13.750 + { 13.751 + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; 13.752 + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; 13.753 + } 13.754 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/libs/openctm/liblzma/LzFind.h Thu Sep 26 04:47:05 2013 +0300 14.3 @@ -0,0 +1,107 @@ 14.4 +/* LzFind.h -- Match finder for LZ algorithms 14.5 +2008-10-04 : Igor Pavlov : Public domain */ 14.6 + 14.7 +#ifndef __LZFIND_H 14.8 +#define __LZFIND_H 14.9 + 14.10 +#include "Types.h" 14.11 + 14.12 +typedef UInt32 CLzRef; 14.13 + 14.14 +typedef struct _CMatchFinder 14.15 +{ 14.16 + Byte *buffer; 14.17 + UInt32 pos; 14.18 + UInt32 posLimit; 14.19 + UInt32 streamPos; 14.20 + UInt32 lenLimit; 14.21 + 14.22 + UInt32 cyclicBufferPos; 14.23 + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ 14.24 + 14.25 + UInt32 matchMaxLen; 14.26 + CLzRef *hash; 14.27 + CLzRef *son; 14.28 + UInt32 hashMask; 14.29 + UInt32 cutValue; 14.30 + 14.31 + Byte *bufferBase; 14.32 + ISeqInStream *stream; 14.33 + int streamEndWasReached; 14.34 + 14.35 + UInt32 blockSize; 14.36 + UInt32 keepSizeBefore; 14.37 + UInt32 keepSizeAfter; 14.38 + 14.39 + UInt32 numHashBytes; 14.40 + int directInput; 14.41 + int btMode; 14.42 + /* int skipModeBits; */ 14.43 + int bigHash; 14.44 + UInt32 historySize; 14.45 + UInt32 fixedHashSize; 14.46 + UInt32 hashSizeSum; 14.47 + UInt32 numSons; 14.48 + SRes result; 14.49 + UInt32 crc[256]; 14.50 +} CMatchFinder; 14.51 + 14.52 +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) 14.53 +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) 14.54 + 14.55 +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) 14.56 + 14.57 +int MatchFinder_NeedMove(CMatchFinder *p); 14.58 +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); 14.59 +void MatchFinder_MoveBlock(CMatchFinder *p); 14.60 +void MatchFinder_ReadIfRequired(CMatchFinder *p); 14.61 + 14.62 +void MatchFinder_Construct(CMatchFinder *p); 14.63 + 14.64 +/* Conditions: 14.65 + historySize <= 3 GB 14.66 + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB 14.67 +*/ 14.68 +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, 14.69 + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, 14.70 + ISzAlloc *alloc); 14.71 +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); 14.72 +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); 14.73 +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); 14.74 + 14.75 +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, 14.76 + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, 14.77 + UInt32 *distances, UInt32 maxLen); 14.78 + 14.79 +/* 14.80 +Conditions: 14.81 + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. 14.82 + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function 14.83 +*/ 14.84 + 14.85 +typedef void (*Mf_Init_Func)(void *object); 14.86 +typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); 14.87 +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); 14.88 +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); 14.89 +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); 14.90 +typedef void (*Mf_Skip_Func)(void *object, UInt32); 14.91 + 14.92 +typedef struct _IMatchFinder 14.93 +{ 14.94 + Mf_Init_Func Init; 14.95 + Mf_GetIndexByte_Func GetIndexByte; 14.96 + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; 14.97 + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; 14.98 + Mf_GetMatches_Func GetMatches; 14.99 + Mf_Skip_Func Skip; 14.100 +} IMatchFinder; 14.101 + 14.102 +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); 14.103 + 14.104 +void MatchFinder_Init(CMatchFinder *p); 14.105 +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); 14.106 +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); 14.107 +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); 14.108 +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); 14.109 + 14.110 +#endif
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/libs/openctm/liblzma/LzHash.h Thu Sep 26 04:47:05 2013 +0300 15.3 @@ -0,0 +1,54 @@ 15.4 +/* LzHash.h -- HASH functions for LZ algorithms 15.5 +2008-10-04 : Igor Pavlov : Public domain */ 15.6 + 15.7 +#ifndef __LZHASH_H 15.8 +#define __LZHASH_H 15.9 + 15.10 +#define kHash2Size (1 << 10) 15.11 +#define kHash3Size (1 << 16) 15.12 +#define kHash4Size (1 << 20) 15.13 + 15.14 +#define kFix3HashSize (kHash2Size) 15.15 +#define kFix4HashSize (kHash2Size + kHash3Size) 15.16 +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) 15.17 + 15.18 +#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); 15.19 + 15.20 +#define HASH3_CALC { \ 15.21 + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 15.22 + hash2Value = temp & (kHash2Size - 1); \ 15.23 + hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } 15.24 + 15.25 +#define HASH4_CALC { \ 15.26 + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 15.27 + hash2Value = temp & (kHash2Size - 1); \ 15.28 + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ 15.29 + hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } 15.30 + 15.31 +#define HASH5_CALC { \ 15.32 + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 15.33 + hash2Value = temp & (kHash2Size - 1); \ 15.34 + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ 15.35 + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ 15.36 + hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ 15.37 + hash4Value &= (kHash4Size - 1); } 15.38 + 15.39 +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ 15.40 +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; 15.41 + 15.42 + 15.43 +#define MT_HASH2_CALC \ 15.44 + hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); 15.45 + 15.46 +#define MT_HASH3_CALC { \ 15.47 + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 15.48 + hash2Value = temp & (kHash2Size - 1); \ 15.49 + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } 15.50 + 15.51 +#define MT_HASH4_CALC { \ 15.52 + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ 15.53 + hash2Value = temp & (kHash2Size - 1); \ 15.54 + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ 15.55 + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } 15.56 + 15.57 +#endif
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/libs/openctm/liblzma/LzmaDec.c Thu Sep 26 04:47:05 2013 +0300 16.3 @@ -0,0 +1,1007 @@ 16.4 +/* LzmaDec.c -- LZMA Decoder 16.5 +2008-11-06 : Igor Pavlov : Public domain */ 16.6 + 16.7 +#include "LzmaDec.h" 16.8 + 16.9 +#include <string.h> 16.10 + 16.11 +#define kNumTopBits 24 16.12 +#define kTopValue ((UInt32)1 << kNumTopBits) 16.13 + 16.14 +#define kNumBitModelTotalBits 11 16.15 +#define kBitModelTotal (1 << kNumBitModelTotalBits) 16.16 +#define kNumMoveBits 5 16.17 + 16.18 +#define RC_INIT_SIZE 5 16.19 + 16.20 +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } 16.21 + 16.22 +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) 16.23 +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); 16.24 +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); 16.25 +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ 16.26 + { UPDATE_0(p); i = (i + i); A0; } else \ 16.27 + { UPDATE_1(p); i = (i + i) + 1; A1; } 16.28 +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) 16.29 + 16.30 +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } 16.31 +#define TREE_DECODE(probs, limit, i) \ 16.32 + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } 16.33 + 16.34 +/* #define _LZMA_SIZE_OPT */ 16.35 + 16.36 +#ifdef _LZMA_SIZE_OPT 16.37 +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) 16.38 +#else 16.39 +#define TREE_6_DECODE(probs, i) \ 16.40 + { i = 1; \ 16.41 + TREE_GET_BIT(probs, i); \ 16.42 + TREE_GET_BIT(probs, i); \ 16.43 + TREE_GET_BIT(probs, i); \ 16.44 + TREE_GET_BIT(probs, i); \ 16.45 + TREE_GET_BIT(probs, i); \ 16.46 + TREE_GET_BIT(probs, i); \ 16.47 + i -= 0x40; } 16.48 +#endif 16.49 + 16.50 +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } 16.51 + 16.52 +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) 16.53 +#define UPDATE_0_CHECK range = bound; 16.54 +#define UPDATE_1_CHECK range -= bound; code -= bound; 16.55 +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ 16.56 + { UPDATE_0_CHECK; i = (i + i); A0; } else \ 16.57 + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } 16.58 +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) 16.59 +#define TREE_DECODE_CHECK(probs, limit, i) \ 16.60 + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } 16.61 + 16.62 + 16.63 +#define kNumPosBitsMax 4 16.64 +#define kNumPosStatesMax (1 << kNumPosBitsMax) 16.65 + 16.66 +#define kLenNumLowBits 3 16.67 +#define kLenNumLowSymbols (1 << kLenNumLowBits) 16.68 +#define kLenNumMidBits 3 16.69 +#define kLenNumMidSymbols (1 << kLenNumMidBits) 16.70 +#define kLenNumHighBits 8 16.71 +#define kLenNumHighSymbols (1 << kLenNumHighBits) 16.72 + 16.73 +#define LenChoice 0 16.74 +#define LenChoice2 (LenChoice + 1) 16.75 +#define LenLow (LenChoice2 + 1) 16.76 +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) 16.77 +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) 16.78 +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 16.79 + 16.80 + 16.81 +#define kNumStates 12 16.82 +#define kNumLitStates 7 16.83 + 16.84 +#define kStartPosModelIndex 4 16.85 +#define kEndPosModelIndex 14 16.86 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) 16.87 + 16.88 +#define kNumPosSlotBits 6 16.89 +#define kNumLenToPosStates 4 16.90 + 16.91 +#define kNumAlignBits 4 16.92 +#define kAlignTableSize (1 << kNumAlignBits) 16.93 + 16.94 +#define kMatchMinLen 2 16.95 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) 16.96 + 16.97 +#define IsMatch 0 16.98 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) 16.99 +#define IsRepG0 (IsRep + kNumStates) 16.100 +#define IsRepG1 (IsRepG0 + kNumStates) 16.101 +#define IsRepG2 (IsRepG1 + kNumStates) 16.102 +#define IsRep0Long (IsRepG2 + kNumStates) 16.103 +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) 16.104 +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) 16.105 +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) 16.106 +#define LenCoder (Align + kAlignTableSize) 16.107 +#define RepLenCoder (LenCoder + kNumLenProbs) 16.108 +#define Literal (RepLenCoder + kNumLenProbs) 16.109 + 16.110 +#define LZMA_BASE_SIZE 1846 16.111 +#define LZMA_LIT_SIZE 768 16.112 + 16.113 +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) 16.114 + 16.115 +#if Literal != LZMA_BASE_SIZE 16.116 +StopCompilingDueBUG 16.117 +#endif 16.118 + 16.119 +static const Byte kLiteralNextStates[kNumStates * 2] = 16.120 +{ 16.121 + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, 16.122 + 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 16.123 +}; 16.124 + 16.125 +#define LZMA_DIC_MIN (1 << 12) 16.126 + 16.127 +/* First LZMA-symbol is always decoded. 16.128 +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization 16.129 +Out: 16.130 + Result: 16.131 + SZ_OK - OK 16.132 + SZ_ERROR_DATA - Error 16.133 + p->remainLen: 16.134 + < kMatchSpecLenStart : normal remain 16.135 + = kMatchSpecLenStart : finished 16.136 + = kMatchSpecLenStart + 1 : Flush marker 16.137 + = kMatchSpecLenStart + 2 : State Init Marker 16.138 +*/ 16.139 + 16.140 +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) 16.141 +{ 16.142 + CLzmaProb *probs = p->probs; 16.143 + 16.144 + unsigned state = p->state; 16.145 + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; 16.146 + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; 16.147 + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; 16.148 + unsigned lc = p->prop.lc; 16.149 + 16.150 + Byte *dic = p->dic; 16.151 + SizeT dicBufSize = p->dicBufSize; 16.152 + SizeT dicPos = p->dicPos; 16.153 + 16.154 + UInt32 processedPos = p->processedPos; 16.155 + UInt32 checkDicSize = p->checkDicSize; 16.156 + unsigned len = 0; 16.157 + 16.158 + const Byte *buf = p->buf; 16.159 + UInt32 range = p->range; 16.160 + UInt32 code = p->code; 16.161 + 16.162 + do 16.163 + { 16.164 + CLzmaProb *prob; 16.165 + UInt32 bound; 16.166 + unsigned ttt; 16.167 + unsigned posState = processedPos & pbMask; 16.168 + 16.169 + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; 16.170 + IF_BIT_0(prob) 16.171 + { 16.172 + unsigned symbol; 16.173 + UPDATE_0(prob); 16.174 + prob = probs + Literal; 16.175 + if (checkDicSize != 0 || processedPos != 0) 16.176 + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + 16.177 + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); 16.178 + 16.179 + if (state < kNumLitStates) 16.180 + { 16.181 + symbol = 1; 16.182 + do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); 16.183 + } 16.184 + else 16.185 + { 16.186 + unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; 16.187 + unsigned offs = 0x100; 16.188 + symbol = 1; 16.189 + do 16.190 + { 16.191 + unsigned bit; 16.192 + CLzmaProb *probLit; 16.193 + matchByte <<= 1; 16.194 + bit = (matchByte & offs); 16.195 + probLit = prob + offs + bit + symbol; 16.196 + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) 16.197 + } 16.198 + while (symbol < 0x100); 16.199 + } 16.200 + dic[dicPos++] = (Byte)symbol; 16.201 + processedPos++; 16.202 + 16.203 + state = kLiteralNextStates[state]; 16.204 + /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ 16.205 + continue; 16.206 + } 16.207 + else 16.208 + { 16.209 + UPDATE_1(prob); 16.210 + prob = probs + IsRep + state; 16.211 + IF_BIT_0(prob) 16.212 + { 16.213 + UPDATE_0(prob); 16.214 + state += kNumStates; 16.215 + prob = probs + LenCoder; 16.216 + } 16.217 + else 16.218 + { 16.219 + UPDATE_1(prob); 16.220 + if (checkDicSize == 0 && processedPos == 0) 16.221 + return SZ_ERROR_DATA; 16.222 + prob = probs + IsRepG0 + state; 16.223 + IF_BIT_0(prob) 16.224 + { 16.225 + UPDATE_0(prob); 16.226 + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; 16.227 + IF_BIT_0(prob) 16.228 + { 16.229 + UPDATE_0(prob); 16.230 + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; 16.231 + dicPos++; 16.232 + processedPos++; 16.233 + state = state < kNumLitStates ? 9 : 11; 16.234 + continue; 16.235 + } 16.236 + UPDATE_1(prob); 16.237 + } 16.238 + else 16.239 + { 16.240 + UInt32 distance; 16.241 + UPDATE_1(prob); 16.242 + prob = probs + IsRepG1 + state; 16.243 + IF_BIT_0(prob) 16.244 + { 16.245 + UPDATE_0(prob); 16.246 + distance = rep1; 16.247 + } 16.248 + else 16.249 + { 16.250 + UPDATE_1(prob); 16.251 + prob = probs + IsRepG2 + state; 16.252 + IF_BIT_0(prob) 16.253 + { 16.254 + UPDATE_0(prob); 16.255 + distance = rep2; 16.256 + } 16.257 + else 16.258 + { 16.259 + UPDATE_1(prob); 16.260 + distance = rep3; 16.261 + rep3 = rep2; 16.262 + } 16.263 + rep2 = rep1; 16.264 + } 16.265 + rep1 = rep0; 16.266 + rep0 = distance; 16.267 + } 16.268 + state = state < kNumLitStates ? 8 : 11; 16.269 + prob = probs + RepLenCoder; 16.270 + } 16.271 + { 16.272 + unsigned limit, offset; 16.273 + CLzmaProb *probLen = prob + LenChoice; 16.274 + IF_BIT_0(probLen) 16.275 + { 16.276 + UPDATE_0(probLen); 16.277 + probLen = prob + LenLow + (posState << kLenNumLowBits); 16.278 + offset = 0; 16.279 + limit = (1 << kLenNumLowBits); 16.280 + } 16.281 + else 16.282 + { 16.283 + UPDATE_1(probLen); 16.284 + probLen = prob + LenChoice2; 16.285 + IF_BIT_0(probLen) 16.286 + { 16.287 + UPDATE_0(probLen); 16.288 + probLen = prob + LenMid + (posState << kLenNumMidBits); 16.289 + offset = kLenNumLowSymbols; 16.290 + limit = (1 << kLenNumMidBits); 16.291 + } 16.292 + else 16.293 + { 16.294 + UPDATE_1(probLen); 16.295 + probLen = prob + LenHigh; 16.296 + offset = kLenNumLowSymbols + kLenNumMidSymbols; 16.297 + limit = (1 << kLenNumHighBits); 16.298 + } 16.299 + } 16.300 + TREE_DECODE(probLen, limit, len); 16.301 + len += offset; 16.302 + } 16.303 + 16.304 + if (state >= kNumStates) 16.305 + { 16.306 + UInt32 distance; 16.307 + prob = probs + PosSlot + 16.308 + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); 16.309 + TREE_6_DECODE(prob, distance); 16.310 + if (distance >= kStartPosModelIndex) 16.311 + { 16.312 + unsigned posSlot = (unsigned)distance; 16.313 + int numDirectBits = (int)(((distance >> 1) - 1)); 16.314 + distance = (2 | (distance & 1)); 16.315 + if (posSlot < kEndPosModelIndex) 16.316 + { 16.317 + distance <<= numDirectBits; 16.318 + prob = probs + SpecPos + distance - posSlot - 1; 16.319 + { 16.320 + UInt32 mask = 1; 16.321 + unsigned i = 1; 16.322 + do 16.323 + { 16.324 + GET_BIT2(prob + i, i, ; , distance |= mask); 16.325 + mask <<= 1; 16.326 + } 16.327 + while (--numDirectBits != 0); 16.328 + } 16.329 + } 16.330 + else 16.331 + { 16.332 + numDirectBits -= kNumAlignBits; 16.333 + do 16.334 + { 16.335 + NORMALIZE 16.336 + range >>= 1; 16.337 + 16.338 + { 16.339 + UInt32 t; 16.340 + code -= range; 16.341 + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ 16.342 + distance = (distance << 1) + (t + 1); 16.343 + code += range & t; 16.344 + } 16.345 + /* 16.346 + distance <<= 1; 16.347 + if (code >= range) 16.348 + { 16.349 + code -= range; 16.350 + distance |= 1; 16.351 + } 16.352 + */ 16.353 + } 16.354 + while (--numDirectBits != 0); 16.355 + prob = probs + Align; 16.356 + distance <<= kNumAlignBits; 16.357 + { 16.358 + unsigned i = 1; 16.359 + GET_BIT2(prob + i, i, ; , distance |= 1); 16.360 + GET_BIT2(prob + i, i, ; , distance |= 2); 16.361 + GET_BIT2(prob + i, i, ; , distance |= 4); 16.362 + GET_BIT2(prob + i, i, ; , distance |= 8); 16.363 + } 16.364 + if (distance == (UInt32)0xFFFFFFFF) 16.365 + { 16.366 + len += kMatchSpecLenStart; 16.367 + state -= kNumStates; 16.368 + break; 16.369 + } 16.370 + } 16.371 + } 16.372 + rep3 = rep2; 16.373 + rep2 = rep1; 16.374 + rep1 = rep0; 16.375 + rep0 = distance + 1; 16.376 + if (checkDicSize == 0) 16.377 + { 16.378 + if (distance >= processedPos) 16.379 + return SZ_ERROR_DATA; 16.380 + } 16.381 + else if (distance >= checkDicSize) 16.382 + return SZ_ERROR_DATA; 16.383 + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; 16.384 + /* state = kLiteralNextStates[state]; */ 16.385 + } 16.386 + 16.387 + len += kMatchMinLen; 16.388 + 16.389 + if (limit == dicPos) 16.390 + return SZ_ERROR_DATA; 16.391 + { 16.392 + SizeT rem = limit - dicPos; 16.393 + unsigned curLen = ((rem < len) ? (unsigned)rem : len); 16.394 + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); 16.395 + 16.396 + processedPos += curLen; 16.397 + 16.398 + len -= curLen; 16.399 + if (pos + curLen <= dicBufSize) 16.400 + { 16.401 + Byte *dest = dic + dicPos; 16.402 + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; 16.403 + const Byte *lim = dest + curLen; 16.404 + dicPos += curLen; 16.405 + do 16.406 + *(dest) = (Byte)*(dest + src); 16.407 + while (++dest != lim); 16.408 + } 16.409 + else 16.410 + { 16.411 + do 16.412 + { 16.413 + dic[dicPos++] = dic[pos]; 16.414 + if (++pos == dicBufSize) 16.415 + pos = 0; 16.416 + } 16.417 + while (--curLen != 0); 16.418 + } 16.419 + } 16.420 + } 16.421 + } 16.422 + while (dicPos < limit && buf < bufLimit); 16.423 + NORMALIZE; 16.424 + p->buf = buf; 16.425 + p->range = range; 16.426 + p->code = code; 16.427 + p->remainLen = len; 16.428 + p->dicPos = dicPos; 16.429 + p->processedPos = processedPos; 16.430 + p->reps[0] = rep0; 16.431 + p->reps[1] = rep1; 16.432 + p->reps[2] = rep2; 16.433 + p->reps[3] = rep3; 16.434 + p->state = state; 16.435 + 16.436 + return SZ_OK; 16.437 +} 16.438 + 16.439 +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) 16.440 +{ 16.441 + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) 16.442 + { 16.443 + Byte *dic = p->dic; 16.444 + SizeT dicPos = p->dicPos; 16.445 + SizeT dicBufSize = p->dicBufSize; 16.446 + unsigned len = p->remainLen; 16.447 + UInt32 rep0 = p->reps[0]; 16.448 + if (limit - dicPos < len) 16.449 + len = (unsigned)(limit - dicPos); 16.450 + 16.451 + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) 16.452 + p->checkDicSize = p->prop.dicSize; 16.453 + 16.454 + p->processedPos += len; 16.455 + p->remainLen -= len; 16.456 + while (len-- != 0) 16.457 + { 16.458 + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; 16.459 + dicPos++; 16.460 + } 16.461 + p->dicPos = dicPos; 16.462 + } 16.463 +} 16.464 + 16.465 +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) 16.466 +{ 16.467 + do 16.468 + { 16.469 + SizeT limit2 = limit; 16.470 + if (p->checkDicSize == 0) 16.471 + { 16.472 + UInt32 rem = p->prop.dicSize - p->processedPos; 16.473 + if (limit - p->dicPos > rem) 16.474 + limit2 = p->dicPos + rem; 16.475 + } 16.476 + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); 16.477 + if (p->processedPos >= p->prop.dicSize) 16.478 + p->checkDicSize = p->prop.dicSize; 16.479 + LzmaDec_WriteRem(p, limit); 16.480 + } 16.481 + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); 16.482 + 16.483 + if (p->remainLen > kMatchSpecLenStart) 16.484 + { 16.485 + p->remainLen = kMatchSpecLenStart; 16.486 + } 16.487 + return 0; 16.488 +} 16.489 + 16.490 +typedef enum 16.491 +{ 16.492 + DUMMY_ERROR, /* unexpected end of input stream */ 16.493 + DUMMY_LIT, 16.494 + DUMMY_MATCH, 16.495 + DUMMY_REP 16.496 +} ELzmaDummy; 16.497 + 16.498 +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) 16.499 +{ 16.500 + UInt32 range = p->range; 16.501 + UInt32 code = p->code; 16.502 + const Byte *bufLimit = buf + inSize; 16.503 + CLzmaProb *probs = p->probs; 16.504 + unsigned state = p->state; 16.505 + ELzmaDummy res; 16.506 + 16.507 + { 16.508 + CLzmaProb *prob; 16.509 + UInt32 bound; 16.510 + unsigned ttt; 16.511 + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); 16.512 + 16.513 + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; 16.514 + IF_BIT_0_CHECK(prob) 16.515 + { 16.516 + UPDATE_0_CHECK 16.517 + 16.518 + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ 16.519 + 16.520 + prob = probs + Literal; 16.521 + if (p->checkDicSize != 0 || p->processedPos != 0) 16.522 + prob += (LZMA_LIT_SIZE * 16.523 + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + 16.524 + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); 16.525 + 16.526 + if (state < kNumLitStates) 16.527 + { 16.528 + unsigned symbol = 1; 16.529 + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); 16.530 + } 16.531 + else 16.532 + { 16.533 + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + 16.534 + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; 16.535 + unsigned offs = 0x100; 16.536 + unsigned symbol = 1; 16.537 + do 16.538 + { 16.539 + unsigned bit; 16.540 + CLzmaProb *probLit; 16.541 + matchByte <<= 1; 16.542 + bit = (matchByte & offs); 16.543 + probLit = prob + offs + bit + symbol; 16.544 + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) 16.545 + } 16.546 + while (symbol < 0x100); 16.547 + } 16.548 + res = DUMMY_LIT; 16.549 + } 16.550 + else 16.551 + { 16.552 + unsigned len; 16.553 + UPDATE_1_CHECK; 16.554 + 16.555 + prob = probs + IsRep + state; 16.556 + IF_BIT_0_CHECK(prob) 16.557 + { 16.558 + UPDATE_0_CHECK; 16.559 + state = 0; 16.560 + prob = probs + LenCoder; 16.561 + res = DUMMY_MATCH; 16.562 + } 16.563 + else 16.564 + { 16.565 + UPDATE_1_CHECK; 16.566 + res = DUMMY_REP; 16.567 + prob = probs + IsRepG0 + state; 16.568 + IF_BIT_0_CHECK(prob) 16.569 + { 16.570 + UPDATE_0_CHECK; 16.571 + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; 16.572 + IF_BIT_0_CHECK(prob) 16.573 + { 16.574 + UPDATE_0_CHECK; 16.575 + NORMALIZE_CHECK; 16.576 + return DUMMY_REP; 16.577 + } 16.578 + else 16.579 + { 16.580 + UPDATE_1_CHECK; 16.581 + } 16.582 + } 16.583 + else 16.584 + { 16.585 + UPDATE_1_CHECK; 16.586 + prob = probs + IsRepG1 + state; 16.587 + IF_BIT_0_CHECK(prob) 16.588 + { 16.589 + UPDATE_0_CHECK; 16.590 + } 16.591 + else 16.592 + { 16.593 + UPDATE_1_CHECK; 16.594 + prob = probs + IsRepG2 + state; 16.595 + IF_BIT_0_CHECK(prob) 16.596 + { 16.597 + UPDATE_0_CHECK; 16.598 + } 16.599 + else 16.600 + { 16.601 + UPDATE_1_CHECK; 16.602 + } 16.603 + } 16.604 + } 16.605 + state = kNumStates; 16.606 + prob = probs + RepLenCoder; 16.607 + } 16.608 + { 16.609 + unsigned limit, offset; 16.610 + CLzmaProb *probLen = prob + LenChoice; 16.611 + IF_BIT_0_CHECK(probLen) 16.612 + { 16.613 + UPDATE_0_CHECK; 16.614 + probLen = prob + LenLow + (posState << kLenNumLowBits); 16.615 + offset = 0; 16.616 + limit = 1 << kLenNumLowBits; 16.617 + } 16.618 + else 16.619 + { 16.620 + UPDATE_1_CHECK; 16.621 + probLen = prob + LenChoice2; 16.622 + IF_BIT_0_CHECK(probLen) 16.623 + { 16.624 + UPDATE_0_CHECK; 16.625 + probLen = prob + LenMid + (posState << kLenNumMidBits); 16.626 + offset = kLenNumLowSymbols; 16.627 + limit = 1 << kLenNumMidBits; 16.628 + } 16.629 + else 16.630 + { 16.631 + UPDATE_1_CHECK; 16.632 + probLen = prob + LenHigh; 16.633 + offset = kLenNumLowSymbols + kLenNumMidSymbols; 16.634 + limit = 1 << kLenNumHighBits; 16.635 + } 16.636 + } 16.637 + TREE_DECODE_CHECK(probLen, limit, len); 16.638 + len += offset; 16.639 + } 16.640 + 16.641 + if (state < 4) 16.642 + { 16.643 + unsigned posSlot; 16.644 + prob = probs + PosSlot + 16.645 + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 16.646 + kNumPosSlotBits); 16.647 + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); 16.648 + if (posSlot >= kStartPosModelIndex) 16.649 + { 16.650 + int numDirectBits = ((posSlot >> 1) - 1); 16.651 + 16.652 + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ 16.653 + 16.654 + if (posSlot < kEndPosModelIndex) 16.655 + { 16.656 + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; 16.657 + } 16.658 + else 16.659 + { 16.660 + numDirectBits -= kNumAlignBits; 16.661 + do 16.662 + { 16.663 + NORMALIZE_CHECK 16.664 + range >>= 1; 16.665 + code -= range & (((code - range) >> 31) - 1); 16.666 + /* if (code >= range) code -= range; */ 16.667 + } 16.668 + while (--numDirectBits != 0); 16.669 + prob = probs + Align; 16.670 + numDirectBits = kNumAlignBits; 16.671 + } 16.672 + { 16.673 + unsigned i = 1; 16.674 + do 16.675 + { 16.676 + GET_BIT_CHECK(prob + i, i); 16.677 + } 16.678 + while (--numDirectBits != 0); 16.679 + } 16.680 + } 16.681 + } 16.682 + } 16.683 + } 16.684 + NORMALIZE_CHECK; 16.685 + return res; 16.686 +} 16.687 + 16.688 + 16.689 +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) 16.690 +{ 16.691 + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); 16.692 + p->range = 0xFFFFFFFF; 16.693 + p->needFlush = 0; 16.694 +} 16.695 + 16.696 +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) 16.697 +{ 16.698 + p->needFlush = 1; 16.699 + p->remainLen = 0; 16.700 + p->tempBufSize = 0; 16.701 + 16.702 + if (initDic) 16.703 + { 16.704 + p->processedPos = 0; 16.705 + p->checkDicSize = 0; 16.706 + p->needInitState = 1; 16.707 + } 16.708 + if (initState) 16.709 + p->needInitState = 1; 16.710 +} 16.711 + 16.712 +void LzmaDec_Init(CLzmaDec *p) 16.713 +{ 16.714 + p->dicPos = 0; 16.715 + LzmaDec_InitDicAndState(p, True, True); 16.716 +} 16.717 + 16.718 +static void LzmaDec_InitStateReal(CLzmaDec *p) 16.719 +{ 16.720 + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); 16.721 + UInt32 i; 16.722 + CLzmaProb *probs = p->probs; 16.723 + for (i = 0; i < numProbs; i++) 16.724 + probs[i] = kBitModelTotal >> 1; 16.725 + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; 16.726 + p->state = 0; 16.727 + p->needInitState = 0; 16.728 +} 16.729 + 16.730 +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, 16.731 + ELzmaFinishMode finishMode, ELzmaStatus *status) 16.732 +{ 16.733 + SizeT inSize = *srcLen; 16.734 + (*srcLen) = 0; 16.735 + LzmaDec_WriteRem(p, dicLimit); 16.736 + 16.737 + *status = LZMA_STATUS_NOT_SPECIFIED; 16.738 + 16.739 + while (p->remainLen != kMatchSpecLenStart) 16.740 + { 16.741 + int checkEndMarkNow; 16.742 + 16.743 + if (p->needFlush != 0) 16.744 + { 16.745 + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) 16.746 + p->tempBuf[p->tempBufSize++] = *src++; 16.747 + if (p->tempBufSize < RC_INIT_SIZE) 16.748 + { 16.749 + *status = LZMA_STATUS_NEEDS_MORE_INPUT; 16.750 + return SZ_OK; 16.751 + } 16.752 + if (p->tempBuf[0] != 0) 16.753 + return SZ_ERROR_DATA; 16.754 + 16.755 + LzmaDec_InitRc(p, p->tempBuf); 16.756 + p->tempBufSize = 0; 16.757 + } 16.758 + 16.759 + checkEndMarkNow = 0; 16.760 + if (p->dicPos >= dicLimit) 16.761 + { 16.762 + if (p->remainLen == 0 && p->code == 0) 16.763 + { 16.764 + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; 16.765 + return SZ_OK; 16.766 + } 16.767 + if (finishMode == LZMA_FINISH_ANY) 16.768 + { 16.769 + *status = LZMA_STATUS_NOT_FINISHED; 16.770 + return SZ_OK; 16.771 + } 16.772 + if (p->remainLen != 0) 16.773 + { 16.774 + *status = LZMA_STATUS_NOT_FINISHED; 16.775 + return SZ_ERROR_DATA; 16.776 + } 16.777 + checkEndMarkNow = 1; 16.778 + } 16.779 + 16.780 + if (p->needInitState) 16.781 + LzmaDec_InitStateReal(p); 16.782 + 16.783 + if (p->tempBufSize == 0) 16.784 + { 16.785 + SizeT processed; 16.786 + const Byte *bufLimit; 16.787 + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) 16.788 + { 16.789 + int dummyRes = LzmaDec_TryDummy(p, src, inSize); 16.790 + if (dummyRes == DUMMY_ERROR) 16.791 + { 16.792 + memcpy(p->tempBuf, src, inSize); 16.793 + p->tempBufSize = (unsigned)inSize; 16.794 + (*srcLen) += inSize; 16.795 + *status = LZMA_STATUS_NEEDS_MORE_INPUT; 16.796 + return SZ_OK; 16.797 + } 16.798 + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) 16.799 + { 16.800 + *status = LZMA_STATUS_NOT_FINISHED; 16.801 + return SZ_ERROR_DATA; 16.802 + } 16.803 + bufLimit = src; 16.804 + } 16.805 + else 16.806 + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; 16.807 + p->buf = src; 16.808 + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) 16.809 + return SZ_ERROR_DATA; 16.810 + processed = (SizeT)(p->buf - src); 16.811 + (*srcLen) += processed; 16.812 + src += processed; 16.813 + inSize -= processed; 16.814 + } 16.815 + else 16.816 + { 16.817 + unsigned rem = p->tempBufSize, lookAhead = 0; 16.818 + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) 16.819 + p->tempBuf[rem++] = src[lookAhead++]; 16.820 + p->tempBufSize = rem; 16.821 + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) 16.822 + { 16.823 + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); 16.824 + if (dummyRes == DUMMY_ERROR) 16.825 + { 16.826 + (*srcLen) += lookAhead; 16.827 + *status = LZMA_STATUS_NEEDS_MORE_INPUT; 16.828 + return SZ_OK; 16.829 + } 16.830 + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) 16.831 + { 16.832 + *status = LZMA_STATUS_NOT_FINISHED; 16.833 + return SZ_ERROR_DATA; 16.834 + } 16.835 + } 16.836 + p->buf = p->tempBuf; 16.837 + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) 16.838 + return SZ_ERROR_DATA; 16.839 + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); 16.840 + (*srcLen) += lookAhead; 16.841 + src += lookAhead; 16.842 + inSize -= lookAhead; 16.843 + p->tempBufSize = 0; 16.844 + } 16.845 + } 16.846 + if (p->code == 0) 16.847 + *status = LZMA_STATUS_FINISHED_WITH_MARK; 16.848 + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; 16.849 +} 16.850 + 16.851 +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) 16.852 +{ 16.853 + SizeT outSize = *destLen; 16.854 + SizeT inSize = *srcLen; 16.855 + *srcLen = *destLen = 0; 16.856 + for (;;) 16.857 + { 16.858 + SizeT inSizeCur = inSize, outSizeCur, dicPos; 16.859 + ELzmaFinishMode curFinishMode; 16.860 + SRes res; 16.861 + if (p->dicPos == p->dicBufSize) 16.862 + p->dicPos = 0; 16.863 + dicPos = p->dicPos; 16.864 + if (outSize > p->dicBufSize - dicPos) 16.865 + { 16.866 + outSizeCur = p->dicBufSize; 16.867 + curFinishMode = LZMA_FINISH_ANY; 16.868 + } 16.869 + else 16.870 + { 16.871 + outSizeCur = dicPos + outSize; 16.872 + curFinishMode = finishMode; 16.873 + } 16.874 + 16.875 + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); 16.876 + src += inSizeCur; 16.877 + inSize -= inSizeCur; 16.878 + *srcLen += inSizeCur; 16.879 + outSizeCur = p->dicPos - dicPos; 16.880 + memcpy(dest, p->dic + dicPos, outSizeCur); 16.881 + dest += outSizeCur; 16.882 + outSize -= outSizeCur; 16.883 + *destLen += outSizeCur; 16.884 + if (res != 0) 16.885 + return res; 16.886 + if (outSizeCur == 0 || outSize == 0) 16.887 + return SZ_OK; 16.888 + } 16.889 +} 16.890 + 16.891 +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) 16.892 +{ 16.893 + alloc->Free(alloc, p->probs); 16.894 + p->probs = 0; 16.895 +} 16.896 + 16.897 +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) 16.898 +{ 16.899 + alloc->Free(alloc, p->dic); 16.900 + p->dic = 0; 16.901 +} 16.902 + 16.903 +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) 16.904 +{ 16.905 + LzmaDec_FreeProbs(p, alloc); 16.906 + LzmaDec_FreeDict(p, alloc); 16.907 +} 16.908 + 16.909 +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) 16.910 +{ 16.911 + UInt32 dicSize; 16.912 + Byte d; 16.913 + 16.914 + if (size < LZMA_PROPS_SIZE) 16.915 + return SZ_ERROR_UNSUPPORTED; 16.916 + else 16.917 + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); 16.918 + 16.919 + if (dicSize < LZMA_DIC_MIN) 16.920 + dicSize = LZMA_DIC_MIN; 16.921 + p->dicSize = dicSize; 16.922 + 16.923 + d = data[0]; 16.924 + if (d >= (9 * 5 * 5)) 16.925 + return SZ_ERROR_UNSUPPORTED; 16.926 + 16.927 + p->lc = d % 9; 16.928 + d /= 9; 16.929 + p->pb = d / 5; 16.930 + p->lp = d % 5; 16.931 + 16.932 + return SZ_OK; 16.933 +} 16.934 + 16.935 +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) 16.936 +{ 16.937 + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); 16.938 + if (p->probs == 0 || numProbs != p->numProbs) 16.939 + { 16.940 + LzmaDec_FreeProbs(p, alloc); 16.941 + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); 16.942 + p->numProbs = numProbs; 16.943 + if (p->probs == 0) 16.944 + return SZ_ERROR_MEM; 16.945 + } 16.946 + return SZ_OK; 16.947 +} 16.948 + 16.949 +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) 16.950 +{ 16.951 + CLzmaProps propNew; 16.952 + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); 16.953 + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); 16.954 + p->prop = propNew; 16.955 + return SZ_OK; 16.956 +} 16.957 + 16.958 +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) 16.959 +{ 16.960 + CLzmaProps propNew; 16.961 + SizeT dicBufSize; 16.962 + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); 16.963 + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); 16.964 + dicBufSize = propNew.dicSize; 16.965 + if (p->dic == 0 || dicBufSize != p->dicBufSize) 16.966 + { 16.967 + LzmaDec_FreeDict(p, alloc); 16.968 + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); 16.969 + if (p->dic == 0) 16.970 + { 16.971 + LzmaDec_FreeProbs(p, alloc); 16.972 + return SZ_ERROR_MEM; 16.973 + } 16.974 + } 16.975 + p->dicBufSize = dicBufSize; 16.976 + p->prop = propNew; 16.977 + return SZ_OK; 16.978 +} 16.979 + 16.980 +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 16.981 + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 16.982 + ELzmaStatus *status, ISzAlloc *alloc) 16.983 +{ 16.984 + CLzmaDec p; 16.985 + SRes res; 16.986 + SizeT inSize = *srcLen; 16.987 + SizeT outSize = *destLen; 16.988 + *srcLen = *destLen = 0; 16.989 + if (inSize < RC_INIT_SIZE) 16.990 + return SZ_ERROR_INPUT_EOF; 16.991 + 16.992 + LzmaDec_Construct(&p); 16.993 + res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); 16.994 + if (res != 0) 16.995 + return res; 16.996 + p.dic = dest; 16.997 + p.dicBufSize = outSize; 16.998 + 16.999 + LzmaDec_Init(&p); 16.1000 + 16.1001 + *srcLen = inSize; 16.1002 + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); 16.1003 + 16.1004 + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) 16.1005 + res = SZ_ERROR_INPUT_EOF; 16.1006 + 16.1007 + (*destLen) = p.dicPos; 16.1008 + LzmaDec_FreeProbs(&p, alloc); 16.1009 + return res; 16.1010 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/libs/openctm/liblzma/LzmaDec.h Thu Sep 26 04:47:05 2013 +0300 17.3 @@ -0,0 +1,223 @@ 17.4 +/* LzmaDec.h -- LZMA Decoder 17.5 +2008-10-04 : Igor Pavlov : Public domain */ 17.6 + 17.7 +#ifndef __LZMADEC_H 17.8 +#define __LZMADEC_H 17.9 + 17.10 +#include "Types.h" 17.11 + 17.12 +/* #define _LZMA_PROB32 */ 17.13 +/* _LZMA_PROB32 can increase the speed on some CPUs, 17.14 + but memory usage for CLzmaDec::probs will be doubled in that case */ 17.15 + 17.16 +#ifdef _LZMA_PROB32 17.17 +#define CLzmaProb UInt32 17.18 +#else 17.19 +#define CLzmaProb UInt16 17.20 +#endif 17.21 + 17.22 + 17.23 +/* ---------- LZMA Properties ---------- */ 17.24 + 17.25 +#define LZMA_PROPS_SIZE 5 17.26 + 17.27 +typedef struct _CLzmaProps 17.28 +{ 17.29 + unsigned lc, lp, pb; 17.30 + UInt32 dicSize; 17.31 +} CLzmaProps; 17.32 + 17.33 +/* LzmaProps_Decode - decodes properties 17.34 +Returns: 17.35 + SZ_OK 17.36 + SZ_ERROR_UNSUPPORTED - Unsupported properties 17.37 +*/ 17.38 + 17.39 +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); 17.40 + 17.41 + 17.42 +/* ---------- LZMA Decoder state ---------- */ 17.43 + 17.44 +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. 17.45 + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ 17.46 + 17.47 +#define LZMA_REQUIRED_INPUT_MAX 20 17.48 + 17.49 +typedef struct 17.50 +{ 17.51 + CLzmaProps prop; 17.52 + CLzmaProb *probs; 17.53 + Byte *dic; 17.54 + const Byte *buf; 17.55 + UInt32 range, code; 17.56 + SizeT dicPos; 17.57 + SizeT dicBufSize; 17.58 + UInt32 processedPos; 17.59 + UInt32 checkDicSize; 17.60 + unsigned state; 17.61 + UInt32 reps[4]; 17.62 + unsigned remainLen; 17.63 + int needFlush; 17.64 + int needInitState; 17.65 + UInt32 numProbs; 17.66 + unsigned tempBufSize; 17.67 + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; 17.68 +} CLzmaDec; 17.69 + 17.70 +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } 17.71 + 17.72 +void LzmaDec_Init(CLzmaDec *p); 17.73 + 17.74 +/* There are two types of LZMA streams: 17.75 + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. 17.76 + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ 17.77 + 17.78 +typedef enum 17.79 +{ 17.80 + LZMA_FINISH_ANY, /* finish at any point */ 17.81 + LZMA_FINISH_END /* block must be finished at the end */ 17.82 +} ELzmaFinishMode; 17.83 + 17.84 +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! 17.85 + 17.86 + You must use LZMA_FINISH_END, when you know that current output buffer 17.87 + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. 17.88 + 17.89 + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, 17.90 + and output value of destLen will be less than output buffer size limit. 17.91 + You can check status result also. 17.92 + 17.93 + You can use multiple checks to test data integrity after full decompression: 17.94 + 1) Check Result and "status" variable. 17.95 + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. 17.96 + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. 17.97 + You must use correct finish mode in that case. */ 17.98 + 17.99 +typedef enum 17.100 +{ 17.101 + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ 17.102 + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ 17.103 + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ 17.104 + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ 17.105 + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ 17.106 +} ELzmaStatus; 17.107 + 17.108 +/* ELzmaStatus is used only as output value for function call */ 17.109 + 17.110 + 17.111 +/* ---------- Interfaces ---------- */ 17.112 + 17.113 +/* There are 3 levels of interfaces: 17.114 + 1) Dictionary Interface 17.115 + 2) Buffer Interface 17.116 + 3) One Call Interface 17.117 + You can select any of these interfaces, but don't mix functions from different 17.118 + groups for same object. */ 17.119 + 17.120 + 17.121 +/* There are two variants to allocate state for Dictionary Interface: 17.122 + 1) LzmaDec_Allocate / LzmaDec_Free 17.123 + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs 17.124 + You can use variant 2, if you set dictionary buffer manually. 17.125 + For Buffer Interface you must always use variant 1. 17.126 + 17.127 +LzmaDec_Allocate* can return: 17.128 + SZ_OK 17.129 + SZ_ERROR_MEM - Memory allocation error 17.130 + SZ_ERROR_UNSUPPORTED - Unsupported properties 17.131 +*/ 17.132 + 17.133 +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); 17.134 +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); 17.135 + 17.136 +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); 17.137 +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); 17.138 + 17.139 +/* ---------- Dictionary Interface ---------- */ 17.140 + 17.141 +/* You can use it, if you want to eliminate the overhead for data copying from 17.142 + dictionary to some other external buffer. 17.143 + You must work with CLzmaDec variables directly in this interface. 17.144 + 17.145 + STEPS: 17.146 + LzmaDec_Constr() 17.147 + LzmaDec_Allocate() 17.148 + for (each new stream) 17.149 + { 17.150 + LzmaDec_Init() 17.151 + while (it needs more decompression) 17.152 + { 17.153 + LzmaDec_DecodeToDic() 17.154 + use data from CLzmaDec::dic and update CLzmaDec::dicPos 17.155 + } 17.156 + } 17.157 + LzmaDec_Free() 17.158 +*/ 17.159 + 17.160 +/* LzmaDec_DecodeToDic 17.161 + 17.162 + The decoding to internal dictionary buffer (CLzmaDec::dic). 17.163 + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! 17.164 + 17.165 +finishMode: 17.166 + It has meaning only if the decoding reaches output limit (dicLimit). 17.167 + LZMA_FINISH_ANY - Decode just dicLimit bytes. 17.168 + LZMA_FINISH_END - Stream must be finished after dicLimit. 17.169 + 17.170 +Returns: 17.171 + SZ_OK 17.172 + status: 17.173 + LZMA_STATUS_FINISHED_WITH_MARK 17.174 + LZMA_STATUS_NOT_FINISHED 17.175 + LZMA_STATUS_NEEDS_MORE_INPUT 17.176 + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 17.177 + SZ_ERROR_DATA - Data error 17.178 +*/ 17.179 + 17.180 +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, 17.181 + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 17.182 + 17.183 + 17.184 +/* ---------- Buffer Interface ---------- */ 17.185 + 17.186 +/* It's zlib-like interface. 17.187 + See LzmaDec_DecodeToDic description for information about STEPS and return results, 17.188 + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need 17.189 + to work with CLzmaDec variables manually. 17.190 + 17.191 +finishMode: 17.192 + It has meaning only if the decoding reaches output limit (*destLen). 17.193 + LZMA_FINISH_ANY - Decode just destLen bytes. 17.194 + LZMA_FINISH_END - Stream must be finished after (*destLen). 17.195 +*/ 17.196 + 17.197 +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 17.198 + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); 17.199 + 17.200 + 17.201 +/* ---------- One Call Interface ---------- */ 17.202 + 17.203 +/* LzmaDecode 17.204 + 17.205 +finishMode: 17.206 + It has meaning only if the decoding reaches output limit (*destLen). 17.207 + LZMA_FINISH_ANY - Decode just destLen bytes. 17.208 + LZMA_FINISH_END - Stream must be finished after (*destLen). 17.209 + 17.210 +Returns: 17.211 + SZ_OK 17.212 + status: 17.213 + LZMA_STATUS_FINISHED_WITH_MARK 17.214 + LZMA_STATUS_NOT_FINISHED 17.215 + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 17.216 + SZ_ERROR_DATA - Data error 17.217 + SZ_ERROR_MEM - Memory allocation error 17.218 + SZ_ERROR_UNSUPPORTED - Unsupported properties 17.219 + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). 17.220 +*/ 17.221 + 17.222 +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 17.223 + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 17.224 + ELzmaStatus *status, ISzAlloc *alloc); 17.225 + 17.226 +#endif
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/libs/openctm/liblzma/LzmaEnc.c Thu Sep 26 04:47:05 2013 +0300 18.3 @@ -0,0 +1,2281 @@ 18.4 +/* LzmaEnc.c -- LZMA Encoder 18.5 +2009-02-02 : Igor Pavlov : Public domain */ 18.6 + 18.7 +#include <string.h> 18.8 + 18.9 +/* #define SHOW_STAT */ 18.10 +/* #define SHOW_STAT2 */ 18.11 + 18.12 +#if defined(SHOW_STAT) || defined(SHOW_STAT2) 18.13 +#include <stdio.h> 18.14 +#endif 18.15 + 18.16 +#include "LzmaEnc.h" 18.17 + 18.18 +#include "LzFind.h" 18.19 +#ifdef COMPRESS_MF_MT 18.20 +#include "LzFindMt.h" 18.21 +#endif 18.22 + 18.23 +#ifdef SHOW_STAT 18.24 +static int ttt = 0; 18.25 +#endif 18.26 + 18.27 +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) 18.28 + 18.29 +#define kBlockSize (9 << 10) 18.30 +#define kUnpackBlockSize (1 << 18) 18.31 +#define kMatchArraySize (1 << 21) 18.32 +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) 18.33 + 18.34 +#define kNumMaxDirectBits (31) 18.35 + 18.36 +#define kNumTopBits 24 18.37 +#define kTopValue ((UInt32)1 << kNumTopBits) 18.38 + 18.39 +#define kNumBitModelTotalBits 11 18.40 +#define kBitModelTotal (1 << kNumBitModelTotalBits) 18.41 +#define kNumMoveBits 5 18.42 +#define kProbInitValue (kBitModelTotal >> 1) 18.43 + 18.44 +#define kNumMoveReducingBits 4 18.45 +#define kNumBitPriceShiftBits 4 18.46 +#define kBitPrice (1 << kNumBitPriceShiftBits) 18.47 + 18.48 +void LzmaEncProps_Init(CLzmaEncProps *p) 18.49 +{ 18.50 + p->level = 5; 18.51 + p->dictSize = p->mc = 0; 18.52 + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; 18.53 + p->writeEndMark = 0; 18.54 +} 18.55 + 18.56 +void LzmaEncProps_Normalize(CLzmaEncProps *p) 18.57 +{ 18.58 + int level = p->level; 18.59 + if (level < 0) level = 5; 18.60 + p->level = level; 18.61 + if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); 18.62 + if (p->lc < 0) p->lc = 3; 18.63 + if (p->lp < 0) p->lp = 0; 18.64 + if (p->pb < 0) p->pb = 2; 18.65 + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); 18.66 + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); 18.67 + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); 18.68 + if (p->numHashBytes < 0) p->numHashBytes = 4; 18.69 + if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); 18.70 + if (p->numThreads < 0) 18.71 + p->numThreads = 18.72 + #ifdef COMPRESS_MF_MT 18.73 + ((p->btMode && p->algo) ? 2 : 1); 18.74 + #else 18.75 + 1; 18.76 + #endif 18.77 +} 18.78 + 18.79 +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) 18.80 +{ 18.81 + CLzmaEncProps props = *props2; 18.82 + LzmaEncProps_Normalize(&props); 18.83 + return props.dictSize; 18.84 +} 18.85 + 18.86 +/* #define LZMA_LOG_BSR */ 18.87 +/* Define it for Intel's CPU */ 18.88 + 18.89 + 18.90 +#ifdef LZMA_LOG_BSR 18.91 + 18.92 +#define kDicLogSizeMaxCompress 30 18.93 + 18.94 +#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } 18.95 + 18.96 +static UInt32 GetPosSlot1(UInt32 pos) 18.97 +{ 18.98 + UInt32 res; 18.99 + BSR2_RET(pos, res); 18.100 + return res; 18.101 +} 18.102 +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } 18.103 +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } 18.104 + 18.105 +#else 18.106 + 18.107 +#define kNumLogBits (9 + (int)sizeof(size_t) / 2) 18.108 +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) 18.109 + 18.110 +void LzmaEnc_FastPosInit(Byte *g_FastPos) 18.111 +{ 18.112 + int c = 2, slotFast; 18.113 + g_FastPos[0] = 0; 18.114 + g_FastPos[1] = 1; 18.115 + 18.116 + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) 18.117 + { 18.118 + UInt32 k = (1 << ((slotFast >> 1) - 1)); 18.119 + UInt32 j; 18.120 + for (j = 0; j < k; j++, c++) 18.121 + g_FastPos[c] = (Byte)slotFast; 18.122 + } 18.123 +} 18.124 + 18.125 +#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ 18.126 + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ 18.127 + res = p->g_FastPos[pos >> i] + (i * 2); } 18.128 +/* 18.129 +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ 18.130 + p->g_FastPos[pos >> 6] + 12 : \ 18.131 + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } 18.132 +*/ 18.133 + 18.134 +#define GetPosSlot1(pos) p->g_FastPos[pos] 18.135 +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } 18.136 +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } 18.137 + 18.138 +#endif 18.139 + 18.140 + 18.141 +#define LZMA_NUM_REPS 4 18.142 + 18.143 +typedef unsigned CState; 18.144 + 18.145 +typedef struct _COptimal 18.146 +{ 18.147 + UInt32 price; 18.148 + 18.149 + CState state; 18.150 + int prev1IsChar; 18.151 + int prev2; 18.152 + 18.153 + UInt32 posPrev2; 18.154 + UInt32 backPrev2; 18.155 + 18.156 + UInt32 posPrev; 18.157 + UInt32 backPrev; 18.158 + UInt32 backs[LZMA_NUM_REPS]; 18.159 +} COptimal; 18.160 + 18.161 +#define kNumOpts (1 << 12) 18.162 + 18.163 +#define kNumLenToPosStates 4 18.164 +#define kNumPosSlotBits 6 18.165 +#define kDicLogSizeMin 0 18.166 +#define kDicLogSizeMax 32 18.167 +#define kDistTableSizeMax (kDicLogSizeMax * 2) 18.168 + 18.169 + 18.170 +#define kNumAlignBits 4 18.171 +#define kAlignTableSize (1 << kNumAlignBits) 18.172 +#define kAlignMask (kAlignTableSize - 1) 18.173 + 18.174 +#define kStartPosModelIndex 4 18.175 +#define kEndPosModelIndex 14 18.176 +#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) 18.177 + 18.178 +#define kNumFullDistances (1 << (kEndPosModelIndex / 2)) 18.179 + 18.180 +#ifdef _LZMA_PROB32 18.181 +#define CLzmaProb UInt32 18.182 +#else 18.183 +#define CLzmaProb UInt16 18.184 +#endif 18.185 + 18.186 +#define LZMA_PB_MAX 4 18.187 +#define LZMA_LC_MAX 8 18.188 +#define LZMA_LP_MAX 4 18.189 + 18.190 +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) 18.191 + 18.192 + 18.193 +#define kLenNumLowBits 3 18.194 +#define kLenNumLowSymbols (1 << kLenNumLowBits) 18.195 +#define kLenNumMidBits 3 18.196 +#define kLenNumMidSymbols (1 << kLenNumMidBits) 18.197 +#define kLenNumHighBits 8 18.198 +#define kLenNumHighSymbols (1 << kLenNumHighBits) 18.199 + 18.200 +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) 18.201 + 18.202 +#define LZMA_MATCH_LEN_MIN 2 18.203 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) 18.204 + 18.205 +#define kNumStates 12 18.206 + 18.207 +typedef struct 18.208 +{ 18.209 + CLzmaProb choice; 18.210 + CLzmaProb choice2; 18.211 + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; 18.212 + CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; 18.213 + CLzmaProb high[kLenNumHighSymbols]; 18.214 +} CLenEnc; 18.215 + 18.216 +typedef struct 18.217 +{ 18.218 + CLenEnc p; 18.219 + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; 18.220 + UInt32 tableSize; 18.221 + UInt32 counters[LZMA_NUM_PB_STATES_MAX]; 18.222 +} CLenPriceEnc; 18.223 + 18.224 +typedef struct _CRangeEnc 18.225 +{ 18.226 + UInt32 range; 18.227 + Byte cache; 18.228 + UInt64 low; 18.229 + UInt64 cacheSize; 18.230 + Byte *buf; 18.231 + Byte *bufLim; 18.232 + Byte *bufBase; 18.233 + ISeqOutStream *outStream; 18.234 + UInt64 processed; 18.235 + SRes res; 18.236 +} CRangeEnc; 18.237 + 18.238 +typedef struct _CSeqInStreamBuf 18.239 +{ 18.240 + ISeqInStream funcTable; 18.241 + const Byte *data; 18.242 + SizeT rem; 18.243 +} CSeqInStreamBuf; 18.244 + 18.245 +static SRes MyRead(void *pp, void *data, size_t *size) 18.246 +{ 18.247 + size_t curSize = *size; 18.248 + CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp; 18.249 + if (p->rem < curSize) 18.250 + curSize = p->rem; 18.251 + memcpy(data, p->data, curSize); 18.252 + p->rem -= curSize; 18.253 + p->data += curSize; 18.254 + *size = curSize; 18.255 + return SZ_OK; 18.256 +} 18.257 + 18.258 +typedef struct 18.259 +{ 18.260 + CLzmaProb *litProbs; 18.261 + 18.262 + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; 18.263 + CLzmaProb isRep[kNumStates]; 18.264 + CLzmaProb isRepG0[kNumStates]; 18.265 + CLzmaProb isRepG1[kNumStates]; 18.266 + CLzmaProb isRepG2[kNumStates]; 18.267 + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; 18.268 + 18.269 + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; 18.270 + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; 18.271 + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; 18.272 + 18.273 + CLenPriceEnc lenEnc; 18.274 + CLenPriceEnc repLenEnc; 18.275 + 18.276 + UInt32 reps[LZMA_NUM_REPS]; 18.277 + UInt32 state; 18.278 +} CSaveState; 18.279 + 18.280 +typedef struct _CLzmaEnc 18.281 +{ 18.282 + IMatchFinder matchFinder; 18.283 + void *matchFinderObj; 18.284 + 18.285 + #ifdef COMPRESS_MF_MT 18.286 + Bool mtMode; 18.287 + CMatchFinderMt matchFinderMt; 18.288 + #endif 18.289 + 18.290 + CMatchFinder matchFinderBase; 18.291 + 18.292 + #ifdef COMPRESS_MF_MT 18.293 + Byte pad[128]; 18.294 + #endif 18.295 + 18.296 + UInt32 optimumEndIndex; 18.297 + UInt32 optimumCurrentIndex; 18.298 + 18.299 + UInt32 longestMatchLength; 18.300 + UInt32 numPairs; 18.301 + UInt32 numAvail; 18.302 + COptimal opt[kNumOpts]; 18.303 + 18.304 + #ifndef LZMA_LOG_BSR 18.305 + Byte g_FastPos[1 << kNumLogBits]; 18.306 + #endif 18.307 + 18.308 + UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; 18.309 + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; 18.310 + UInt32 numFastBytes; 18.311 + UInt32 additionalOffset; 18.312 + UInt32 reps[LZMA_NUM_REPS]; 18.313 + UInt32 state; 18.314 + 18.315 + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; 18.316 + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; 18.317 + UInt32 alignPrices[kAlignTableSize]; 18.318 + UInt32 alignPriceCount; 18.319 + 18.320 + UInt32 distTableSize; 18.321 + 18.322 + unsigned lc, lp, pb; 18.323 + unsigned lpMask, pbMask; 18.324 + 18.325 + CLzmaProb *litProbs; 18.326 + 18.327 + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; 18.328 + CLzmaProb isRep[kNumStates]; 18.329 + CLzmaProb isRepG0[kNumStates]; 18.330 + CLzmaProb isRepG1[kNumStates]; 18.331 + CLzmaProb isRepG2[kNumStates]; 18.332 + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; 18.333 + 18.334 + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; 18.335 + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; 18.336 + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; 18.337 + 18.338 + CLenPriceEnc lenEnc; 18.339 + CLenPriceEnc repLenEnc; 18.340 + 18.341 + unsigned lclp; 18.342 + 18.343 + Bool fastMode; 18.344 + 18.345 + CRangeEnc rc; 18.346 + 18.347 + Bool writeEndMark; 18.348 + UInt64 nowPos64; 18.349 + UInt32 matchPriceCount; 18.350 + Bool finished; 18.351 + Bool multiThread; 18.352 + 18.353 + SRes result; 18.354 + UInt32 dictSize; 18.355 + UInt32 matchFinderCycles; 18.356 + 18.357 + ISeqInStream *inStream; 18.358 + CSeqInStreamBuf seqBufInStream; 18.359 + 18.360 + CSaveState saveState; 18.361 +} CLzmaEnc; 18.362 + 18.363 +void LzmaEnc_SaveState(CLzmaEncHandle pp) 18.364 +{ 18.365 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.366 + CSaveState *dest = &p->saveState; 18.367 + int i; 18.368 + dest->lenEnc = p->lenEnc; 18.369 + dest->repLenEnc = p->repLenEnc; 18.370 + dest->state = p->state; 18.371 + 18.372 + for (i = 0; i < kNumStates; i++) 18.373 + { 18.374 + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); 18.375 + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); 18.376 + } 18.377 + for (i = 0; i < kNumLenToPosStates; i++) 18.378 + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); 18.379 + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); 18.380 + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); 18.381 + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); 18.382 + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); 18.383 + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); 18.384 + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); 18.385 + memcpy(dest->reps, p->reps, sizeof(p->reps)); 18.386 + memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); 18.387 +} 18.388 + 18.389 +void LzmaEnc_RestoreState(CLzmaEncHandle pp) 18.390 +{ 18.391 + CLzmaEnc *dest = (CLzmaEnc *)pp; 18.392 + const CSaveState *p = &dest->saveState; 18.393 + int i; 18.394 + dest->lenEnc = p->lenEnc; 18.395 + dest->repLenEnc = p->repLenEnc; 18.396 + dest->state = p->state; 18.397 + 18.398 + for (i = 0; i < kNumStates; i++) 18.399 + { 18.400 + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); 18.401 + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); 18.402 + } 18.403 + for (i = 0; i < kNumLenToPosStates; i++) 18.404 + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); 18.405 + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); 18.406 + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); 18.407 + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); 18.408 + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); 18.409 + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); 18.410 + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); 18.411 + memcpy(dest->reps, p->reps, sizeof(p->reps)); 18.412 + memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); 18.413 +} 18.414 + 18.415 +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) 18.416 +{ 18.417 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.418 + CLzmaEncProps props = *props2; 18.419 + LzmaEncProps_Normalize(&props); 18.420 + 18.421 + if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || 18.422 + props.dictSize > (1U << kDicLogSizeMaxCompress) || props.dictSize > (1U << 30)) 18.423 + return SZ_ERROR_PARAM; 18.424 + p->dictSize = props.dictSize; 18.425 + p->matchFinderCycles = props.mc; 18.426 + { 18.427 + unsigned fb = props.fb; 18.428 + if (fb < 5) 18.429 + fb = 5; 18.430 + if (fb > LZMA_MATCH_LEN_MAX) 18.431 + fb = LZMA_MATCH_LEN_MAX; 18.432 + p->numFastBytes = fb; 18.433 + } 18.434 + p->lc = props.lc; 18.435 + p->lp = props.lp; 18.436 + p->pb = props.pb; 18.437 + p->fastMode = (props.algo == 0); 18.438 + p->matchFinderBase.btMode = props.btMode; 18.439 + { 18.440 + UInt32 numHashBytes = 4; 18.441 + if (props.btMode) 18.442 + { 18.443 + if (props.numHashBytes < 2) 18.444 + numHashBytes = 2; 18.445 + else if (props.numHashBytes < 4) 18.446 + numHashBytes = props.numHashBytes; 18.447 + } 18.448 + p->matchFinderBase.numHashBytes = numHashBytes; 18.449 + } 18.450 + 18.451 + p->matchFinderBase.cutValue = props.mc; 18.452 + 18.453 + p->writeEndMark = props.writeEndMark; 18.454 + 18.455 + #ifdef COMPRESS_MF_MT 18.456 + /* 18.457 + if (newMultiThread != _multiThread) 18.458 + { 18.459 + ReleaseMatchFinder(); 18.460 + _multiThread = newMultiThread; 18.461 + } 18.462 + */ 18.463 + p->multiThread = (props.numThreads > 1); 18.464 + #endif 18.465 + 18.466 + return SZ_OK; 18.467 +} 18.468 + 18.469 +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; 18.470 +static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; 18.471 +static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; 18.472 +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; 18.473 + 18.474 +#define IsCharState(s) ((s) < 7) 18.475 + 18.476 +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) 18.477 + 18.478 +#define kInfinityPrice (1 << 30) 18.479 + 18.480 +static void RangeEnc_Construct(CRangeEnc *p) 18.481 +{ 18.482 + p->outStream = 0; 18.483 + p->bufBase = 0; 18.484 +} 18.485 + 18.486 +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) 18.487 + 18.488 +#define RC_BUF_SIZE (1 << 16) 18.489 +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) 18.490 +{ 18.491 + if (p->bufBase == 0) 18.492 + { 18.493 + p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); 18.494 + if (p->bufBase == 0) 18.495 + return 0; 18.496 + p->bufLim = p->bufBase + RC_BUF_SIZE; 18.497 + } 18.498 + return 1; 18.499 +} 18.500 + 18.501 +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) 18.502 +{ 18.503 + alloc->Free(alloc, p->bufBase); 18.504 + p->bufBase = 0; 18.505 +} 18.506 + 18.507 +static void RangeEnc_Init(CRangeEnc *p) 18.508 +{ 18.509 + /* Stream.Init(); */ 18.510 + p->low = 0; 18.511 + p->range = 0xFFFFFFFF; 18.512 + p->cacheSize = 1; 18.513 + p->cache = 0; 18.514 + 18.515 + p->buf = p->bufBase; 18.516 + 18.517 + p->processed = 0; 18.518 + p->res = SZ_OK; 18.519 +} 18.520 + 18.521 +static void RangeEnc_FlushStream(CRangeEnc *p) 18.522 +{ 18.523 + size_t num; 18.524 + if (p->res != SZ_OK) 18.525 + return; 18.526 + num = p->buf - p->bufBase; 18.527 + if (num != p->outStream->Write(p->outStream, p->bufBase, num)) 18.528 + p->res = SZ_ERROR_WRITE; 18.529 + p->processed += num; 18.530 + p->buf = p->bufBase; 18.531 +} 18.532 + 18.533 +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) 18.534 +{ 18.535 + if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0) 18.536 + { 18.537 + Byte temp = p->cache; 18.538 + do 18.539 + { 18.540 + Byte *buf = p->buf; 18.541 + *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); 18.542 + p->buf = buf; 18.543 + if (buf == p->bufLim) 18.544 + RangeEnc_FlushStream(p); 18.545 + temp = 0xFF; 18.546 + } 18.547 + while (--p->cacheSize != 0); 18.548 + p->cache = (Byte)((UInt32)p->low >> 24); 18.549 + } 18.550 + p->cacheSize++; 18.551 + p->low = (UInt32)p->low << 8; 18.552 +} 18.553 + 18.554 +static void RangeEnc_FlushData(CRangeEnc *p) 18.555 +{ 18.556 + int i; 18.557 + for (i = 0; i < 5; i++) 18.558 + RangeEnc_ShiftLow(p); 18.559 +} 18.560 + 18.561 +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits) 18.562 +{ 18.563 + do 18.564 + { 18.565 + p->range >>= 1; 18.566 + p->low += p->range & (0 - ((value >> --numBits) & 1)); 18.567 + if (p->range < kTopValue) 18.568 + { 18.569 + p->range <<= 8; 18.570 + RangeEnc_ShiftLow(p); 18.571 + } 18.572 + } 18.573 + while (numBits != 0); 18.574 +} 18.575 + 18.576 +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) 18.577 +{ 18.578 + UInt32 ttt = *prob; 18.579 + UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; 18.580 + if (symbol == 0) 18.581 + { 18.582 + p->range = newBound; 18.583 + ttt += (kBitModelTotal - ttt) >> kNumMoveBits; 18.584 + } 18.585 + else 18.586 + { 18.587 + p->low += newBound; 18.588 + p->range -= newBound; 18.589 + ttt -= ttt >> kNumMoveBits; 18.590 + } 18.591 + *prob = (CLzmaProb)ttt; 18.592 + if (p->range < kTopValue) 18.593 + { 18.594 + p->range <<= 8; 18.595 + RangeEnc_ShiftLow(p); 18.596 + } 18.597 +} 18.598 + 18.599 +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) 18.600 +{ 18.601 + symbol |= 0x100; 18.602 + do 18.603 + { 18.604 + RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); 18.605 + symbol <<= 1; 18.606 + } 18.607 + while (symbol < 0x10000); 18.608 +} 18.609 + 18.610 +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) 18.611 +{ 18.612 + UInt32 offs = 0x100; 18.613 + symbol |= 0x100; 18.614 + do 18.615 + { 18.616 + matchByte <<= 1; 18.617 + RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); 18.618 + symbol <<= 1; 18.619 + offs &= ~(matchByte ^ symbol); 18.620 + } 18.621 + while (symbol < 0x10000); 18.622 +} 18.623 + 18.624 +void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) 18.625 +{ 18.626 + UInt32 i; 18.627 + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) 18.628 + { 18.629 + const int kCyclesBits = kNumBitPriceShiftBits; 18.630 + UInt32 w = i; 18.631 + UInt32 bitCount = 0; 18.632 + int j; 18.633 + for (j = 0; j < kCyclesBits; j++) 18.634 + { 18.635 + w = w * w; 18.636 + bitCount <<= 1; 18.637 + while (w >= ((UInt32)1 << 16)) 18.638 + { 18.639 + w >>= 1; 18.640 + bitCount++; 18.641 + } 18.642 + } 18.643 + ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); 18.644 + } 18.645 +} 18.646 + 18.647 + 18.648 +#define GET_PRICE(prob, symbol) \ 18.649 + p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; 18.650 + 18.651 +#define GET_PRICEa(prob, symbol) \ 18.652 + ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; 18.653 + 18.654 +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] 18.655 +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] 18.656 + 18.657 +#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] 18.658 +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] 18.659 + 18.660 +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) 18.661 +{ 18.662 + UInt32 price = 0; 18.663 + symbol |= 0x100; 18.664 + do 18.665 + { 18.666 + price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); 18.667 + symbol <<= 1; 18.668 + } 18.669 + while (symbol < 0x10000); 18.670 + return price; 18.671 +} 18.672 + 18.673 +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) 18.674 +{ 18.675 + UInt32 price = 0; 18.676 + UInt32 offs = 0x100; 18.677 + symbol |= 0x100; 18.678 + do 18.679 + { 18.680 + matchByte <<= 1; 18.681 + price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); 18.682 + symbol <<= 1; 18.683 + offs &= ~(matchByte ^ symbol); 18.684 + } 18.685 + while (symbol < 0x10000); 18.686 + return price; 18.687 +} 18.688 + 18.689 + 18.690 +static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) 18.691 +{ 18.692 + UInt32 m = 1; 18.693 + int i; 18.694 + for (i = numBitLevels; i != 0;) 18.695 + { 18.696 + UInt32 bit; 18.697 + i--; 18.698 + bit = (symbol >> i) & 1; 18.699 + RangeEnc_EncodeBit(rc, probs + m, bit); 18.700 + m = (m << 1) | bit; 18.701 + } 18.702 +} 18.703 + 18.704 +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) 18.705 +{ 18.706 + UInt32 m = 1; 18.707 + int i; 18.708 + for (i = 0; i < numBitLevels; i++) 18.709 + { 18.710 + UInt32 bit = symbol & 1; 18.711 + RangeEnc_EncodeBit(rc, probs + m, bit); 18.712 + m = (m << 1) | bit; 18.713 + symbol >>= 1; 18.714 + } 18.715 +} 18.716 + 18.717 +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) 18.718 +{ 18.719 + UInt32 price = 0; 18.720 + symbol |= (1 << numBitLevels); 18.721 + while (symbol != 1) 18.722 + { 18.723 + price += GET_PRICEa(probs[symbol >> 1], symbol & 1); 18.724 + symbol >>= 1; 18.725 + } 18.726 + return price; 18.727 +} 18.728 + 18.729 +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) 18.730 +{ 18.731 + UInt32 price = 0; 18.732 + UInt32 m = 1; 18.733 + int i; 18.734 + for (i = numBitLevels; i != 0; i--) 18.735 + { 18.736 + UInt32 bit = symbol & 1; 18.737 + symbol >>= 1; 18.738 + price += GET_PRICEa(probs[m], bit); 18.739 + m = (m << 1) | bit; 18.740 + } 18.741 + return price; 18.742 +} 18.743 + 18.744 + 18.745 +static void LenEnc_Init(CLenEnc *p) 18.746 +{ 18.747 + unsigned i; 18.748 + p->choice = p->choice2 = kProbInitValue; 18.749 + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) 18.750 + p->low[i] = kProbInitValue; 18.751 + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) 18.752 + p->mid[i] = kProbInitValue; 18.753 + for (i = 0; i < kLenNumHighSymbols; i++) 18.754 + p->high[i] = kProbInitValue; 18.755 +} 18.756 + 18.757 +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) 18.758 +{ 18.759 + if (symbol < kLenNumLowSymbols) 18.760 + { 18.761 + RangeEnc_EncodeBit(rc, &p->choice, 0); 18.762 + RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); 18.763 + } 18.764 + else 18.765 + { 18.766 + RangeEnc_EncodeBit(rc, &p->choice, 1); 18.767 + if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) 18.768 + { 18.769 + RangeEnc_EncodeBit(rc, &p->choice2, 0); 18.770 + RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); 18.771 + } 18.772 + else 18.773 + { 18.774 + RangeEnc_EncodeBit(rc, &p->choice2, 1); 18.775 + RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); 18.776 + } 18.777 + } 18.778 +} 18.779 + 18.780 +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) 18.781 +{ 18.782 + UInt32 a0 = GET_PRICE_0a(p->choice); 18.783 + UInt32 a1 = GET_PRICE_1a(p->choice); 18.784 + UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); 18.785 + UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); 18.786 + UInt32 i = 0; 18.787 + for (i = 0; i < kLenNumLowSymbols; i++) 18.788 + { 18.789 + if (i >= numSymbols) 18.790 + return; 18.791 + prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); 18.792 + } 18.793 + for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) 18.794 + { 18.795 + if (i >= numSymbols) 18.796 + return; 18.797 + prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); 18.798 + } 18.799 + for (; i < numSymbols; i++) 18.800 + prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); 18.801 +} 18.802 + 18.803 +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) 18.804 +{ 18.805 + LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); 18.806 + p->counters[posState] = p->tableSize; 18.807 +} 18.808 + 18.809 +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) 18.810 +{ 18.811 + UInt32 posState; 18.812 + for (posState = 0; posState < numPosStates; posState++) 18.813 + LenPriceEnc_UpdateTable(p, posState, ProbPrices); 18.814 +} 18.815 + 18.816 +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) 18.817 +{ 18.818 + LenEnc_Encode(&p->p, rc, symbol, posState); 18.819 + if (updatePrice) 18.820 + if (--p->counters[posState] == 0) 18.821 + LenPriceEnc_UpdateTable(p, posState, ProbPrices); 18.822 +} 18.823 + 18.824 + 18.825 + 18.826 + 18.827 +static void MovePos(CLzmaEnc *p, UInt32 num) 18.828 +{ 18.829 + #ifdef SHOW_STAT 18.830 + ttt += num; 18.831 + printf("\n MovePos %d", num); 18.832 + #endif 18.833 + if (num != 0) 18.834 + { 18.835 + p->additionalOffset += num; 18.836 + p->matchFinder.Skip(p->matchFinderObj, num); 18.837 + } 18.838 +} 18.839 + 18.840 +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) 18.841 +{ 18.842 + UInt32 lenRes = 0, numPairs; 18.843 + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); 18.844 + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); 18.845 + #ifdef SHOW_STAT 18.846 + printf("\n i = %d numPairs = %d ", ttt, numPairs / 2); 18.847 + ttt++; 18.848 + { 18.849 + UInt32 i; 18.850 + for (i = 0; i < numPairs; i += 2) 18.851 + printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); 18.852 + } 18.853 + #endif 18.854 + if (numPairs > 0) 18.855 + { 18.856 + lenRes = p->matches[numPairs - 2]; 18.857 + if (lenRes == p->numFastBytes) 18.858 + { 18.859 + const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; 18.860 + UInt32 distance = p->matches[numPairs - 1] + 1; 18.861 + UInt32 numAvail = p->numAvail; 18.862 + if (numAvail > LZMA_MATCH_LEN_MAX) 18.863 + numAvail = LZMA_MATCH_LEN_MAX; 18.864 + { 18.865 + const Byte *pby2 = pby - distance; 18.866 + for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); 18.867 + } 18.868 + } 18.869 + } 18.870 + p->additionalOffset++; 18.871 + *numDistancePairsRes = numPairs; 18.872 + return lenRes; 18.873 +} 18.874 + 18.875 + 18.876 +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; 18.877 +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; 18.878 +#define IsShortRep(p) ((p)->backPrev == 0) 18.879 + 18.880 +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) 18.881 +{ 18.882 + return 18.883 + GET_PRICE_0(p->isRepG0[state]) + 18.884 + GET_PRICE_0(p->isRep0Long[state][posState]); 18.885 +} 18.886 + 18.887 +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) 18.888 +{ 18.889 + UInt32 price; 18.890 + if (repIndex == 0) 18.891 + { 18.892 + price = GET_PRICE_0(p->isRepG0[state]); 18.893 + price += GET_PRICE_1(p->isRep0Long[state][posState]); 18.894 + } 18.895 + else 18.896 + { 18.897 + price = GET_PRICE_1(p->isRepG0[state]); 18.898 + if (repIndex == 1) 18.899 + price += GET_PRICE_0(p->isRepG1[state]); 18.900 + else 18.901 + { 18.902 + price += GET_PRICE_1(p->isRepG1[state]); 18.903 + price += GET_PRICE(p->isRepG2[state], repIndex - 2); 18.904 + } 18.905 + } 18.906 + return price; 18.907 +} 18.908 + 18.909 +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) 18.910 +{ 18.911 + return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + 18.912 + GetPureRepPrice(p, repIndex, state, posState); 18.913 +} 18.914 + 18.915 +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) 18.916 +{ 18.917 + UInt32 posMem = p->opt[cur].posPrev; 18.918 + UInt32 backMem = p->opt[cur].backPrev; 18.919 + p->optimumEndIndex = cur; 18.920 + do 18.921 + { 18.922 + if (p->opt[cur].prev1IsChar) 18.923 + { 18.924 + MakeAsChar(&p->opt[posMem]) 18.925 + p->opt[posMem].posPrev = posMem - 1; 18.926 + if (p->opt[cur].prev2) 18.927 + { 18.928 + p->opt[posMem - 1].prev1IsChar = False; 18.929 + p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; 18.930 + p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; 18.931 + } 18.932 + } 18.933 + { 18.934 + UInt32 posPrev = posMem; 18.935 + UInt32 backCur = backMem; 18.936 + 18.937 + backMem = p->opt[posPrev].backPrev; 18.938 + posMem = p->opt[posPrev].posPrev; 18.939 + 18.940 + p->opt[posPrev].backPrev = backCur; 18.941 + p->opt[posPrev].posPrev = cur; 18.942 + cur = posPrev; 18.943 + } 18.944 + } 18.945 + while (cur != 0); 18.946 + *backRes = p->opt[0].backPrev; 18.947 + p->optimumCurrentIndex = p->opt[0].posPrev; 18.948 + return p->optimumCurrentIndex; 18.949 +} 18.950 + 18.951 +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) 18.952 + 18.953 +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) 18.954 +{ 18.955 + UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; 18.956 + UInt32 matchPrice, repMatchPrice, normalMatchPrice; 18.957 + UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; 18.958 + UInt32 *matches; 18.959 + const Byte *data; 18.960 + Byte curByte, matchByte; 18.961 + if (p->optimumEndIndex != p->optimumCurrentIndex) 18.962 + { 18.963 + const COptimal *opt = &p->opt[p->optimumCurrentIndex]; 18.964 + UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; 18.965 + *backRes = opt->backPrev; 18.966 + p->optimumCurrentIndex = opt->posPrev; 18.967 + return lenRes; 18.968 + } 18.969 + p->optimumCurrentIndex = p->optimumEndIndex = 0; 18.970 + 18.971 + if (p->additionalOffset == 0) 18.972 + mainLen = ReadMatchDistances(p, &numPairs); 18.973 + else 18.974 + { 18.975 + mainLen = p->longestMatchLength; 18.976 + numPairs = p->numPairs; 18.977 + } 18.978 + 18.979 + numAvail = p->numAvail; 18.980 + if (numAvail < 2) 18.981 + { 18.982 + *backRes = (UInt32)(-1); 18.983 + return 1; 18.984 + } 18.985 + if (numAvail > LZMA_MATCH_LEN_MAX) 18.986 + numAvail = LZMA_MATCH_LEN_MAX; 18.987 + 18.988 + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; 18.989 + repMaxIndex = 0; 18.990 + for (i = 0; i < LZMA_NUM_REPS; i++) 18.991 + { 18.992 + UInt32 lenTest; 18.993 + const Byte *data2; 18.994 + reps[i] = p->reps[i]; 18.995 + data2 = data - (reps[i] + 1); 18.996 + if (data[0] != data2[0] || data[1] != data2[1]) 18.997 + { 18.998 + repLens[i] = 0; 18.999 + continue; 18.1000 + } 18.1001 + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); 18.1002 + repLens[i] = lenTest; 18.1003 + if (lenTest > repLens[repMaxIndex]) 18.1004 + repMaxIndex = i; 18.1005 + } 18.1006 + if (repLens[repMaxIndex] >= p->numFastBytes) 18.1007 + { 18.1008 + UInt32 lenRes; 18.1009 + *backRes = repMaxIndex; 18.1010 + lenRes = repLens[repMaxIndex]; 18.1011 + MovePos(p, lenRes - 1); 18.1012 + return lenRes; 18.1013 + } 18.1014 + 18.1015 + matches = p->matches; 18.1016 + if (mainLen >= p->numFastBytes) 18.1017 + { 18.1018 + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; 18.1019 + MovePos(p, mainLen - 1); 18.1020 + return mainLen; 18.1021 + } 18.1022 + curByte = *data; 18.1023 + matchByte = *(data - (reps[0] + 1)); 18.1024 + 18.1025 + if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) 18.1026 + { 18.1027 + *backRes = (UInt32)-1; 18.1028 + return 1; 18.1029 + } 18.1030 + 18.1031 + p->opt[0].state = (CState)p->state; 18.1032 + 18.1033 + posState = (position & p->pbMask); 18.1034 + 18.1035 + { 18.1036 + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); 18.1037 + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + 18.1038 + (!IsCharState(p->state) ? 18.1039 + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : 18.1040 + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); 18.1041 + } 18.1042 + 18.1043 + MakeAsChar(&p->opt[1]); 18.1044 + 18.1045 + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); 18.1046 + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); 18.1047 + 18.1048 + if (matchByte == curByte) 18.1049 + { 18.1050 + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); 18.1051 + if (shortRepPrice < p->opt[1].price) 18.1052 + { 18.1053 + p->opt[1].price = shortRepPrice; 18.1054 + MakeAsShortRep(&p->opt[1]); 18.1055 + } 18.1056 + } 18.1057 + lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); 18.1058 + 18.1059 + if (lenEnd < 2) 18.1060 + { 18.1061 + *backRes = p->opt[1].backPrev; 18.1062 + return 1; 18.1063 + } 18.1064 + 18.1065 + p->opt[1].posPrev = 0; 18.1066 + for (i = 0; i < LZMA_NUM_REPS; i++) 18.1067 + p->opt[0].backs[i] = reps[i]; 18.1068 + 18.1069 + len = lenEnd; 18.1070 + do 18.1071 + p->opt[len--].price = kInfinityPrice; 18.1072 + while (len >= 2); 18.1073 + 18.1074 + for (i = 0; i < LZMA_NUM_REPS; i++) 18.1075 + { 18.1076 + UInt32 repLen = repLens[i]; 18.1077 + UInt32 price; 18.1078 + if (repLen < 2) 18.1079 + continue; 18.1080 + price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); 18.1081 + do 18.1082 + { 18.1083 + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; 18.1084 + COptimal *opt = &p->opt[repLen]; 18.1085 + if (curAndLenPrice < opt->price) 18.1086 + { 18.1087 + opt->price = curAndLenPrice; 18.1088 + opt->posPrev = 0; 18.1089 + opt->backPrev = i; 18.1090 + opt->prev1IsChar = False; 18.1091 + } 18.1092 + } 18.1093 + while (--repLen >= 2); 18.1094 + } 18.1095 + 18.1096 + normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); 18.1097 + 18.1098 + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); 18.1099 + if (len <= mainLen) 18.1100 + { 18.1101 + UInt32 offs = 0; 18.1102 + while (len > matches[offs]) 18.1103 + offs += 2; 18.1104 + for (; ; len++) 18.1105 + { 18.1106 + COptimal *opt; 18.1107 + UInt32 distance = matches[offs + 1]; 18.1108 + 18.1109 + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; 18.1110 + UInt32 lenToPosState = GetLenToPosState(len); 18.1111 + if (distance < kNumFullDistances) 18.1112 + curAndLenPrice += p->distancesPrices[lenToPosState][distance]; 18.1113 + else 18.1114 + { 18.1115 + UInt32 slot; 18.1116 + GetPosSlot2(distance, slot); 18.1117 + curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; 18.1118 + } 18.1119 + opt = &p->opt[len]; 18.1120 + if (curAndLenPrice < opt->price) 18.1121 + { 18.1122 + opt->price = curAndLenPrice; 18.1123 + opt->posPrev = 0; 18.1124 + opt->backPrev = distance + LZMA_NUM_REPS; 18.1125 + opt->prev1IsChar = False; 18.1126 + } 18.1127 + if (len == matches[offs]) 18.1128 + { 18.1129 + offs += 2; 18.1130 + if (offs == numPairs) 18.1131 + break; 18.1132 + } 18.1133 + } 18.1134 + } 18.1135 + 18.1136 + cur = 0; 18.1137 + 18.1138 + #ifdef SHOW_STAT2 18.1139 + if (position >= 0) 18.1140 + { 18.1141 + unsigned i; 18.1142 + printf("\n pos = %4X", position); 18.1143 + for (i = cur; i <= lenEnd; i++) 18.1144 + printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); 18.1145 + } 18.1146 + #endif 18.1147 + 18.1148 + for (;;) 18.1149 + { 18.1150 + UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; 18.1151 + UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; 18.1152 + Bool nextIsChar; 18.1153 + Byte curByte, matchByte; 18.1154 + const Byte *data; 18.1155 + COptimal *curOpt; 18.1156 + COptimal *nextOpt; 18.1157 + 18.1158 + cur++; 18.1159 + if (cur == lenEnd) 18.1160 + return Backward(p, backRes, cur); 18.1161 + 18.1162 + newLen = ReadMatchDistances(p, &numPairs); 18.1163 + if (newLen >= p->numFastBytes) 18.1164 + { 18.1165 + p->numPairs = numPairs; 18.1166 + p->longestMatchLength = newLen; 18.1167 + return Backward(p, backRes, cur); 18.1168 + } 18.1169 + position++; 18.1170 + curOpt = &p->opt[cur]; 18.1171 + posPrev = curOpt->posPrev; 18.1172 + if (curOpt->prev1IsChar) 18.1173 + { 18.1174 + posPrev--; 18.1175 + if (curOpt->prev2) 18.1176 + { 18.1177 + state = p->opt[curOpt->posPrev2].state; 18.1178 + if (curOpt->backPrev2 < LZMA_NUM_REPS) 18.1179 + state = kRepNextStates[state]; 18.1180 + else 18.1181 + state = kMatchNextStates[state]; 18.1182 + } 18.1183 + else 18.1184 + state = p->opt[posPrev].state; 18.1185 + state = kLiteralNextStates[state]; 18.1186 + } 18.1187 + else 18.1188 + state = p->opt[posPrev].state; 18.1189 + if (posPrev == cur - 1) 18.1190 + { 18.1191 + if (IsShortRep(curOpt)) 18.1192 + state = kShortRepNextStates[state]; 18.1193 + else 18.1194 + state = kLiteralNextStates[state]; 18.1195 + } 18.1196 + else 18.1197 + { 18.1198 + UInt32 pos; 18.1199 + const COptimal *prevOpt; 18.1200 + if (curOpt->prev1IsChar && curOpt->prev2) 18.1201 + { 18.1202 + posPrev = curOpt->posPrev2; 18.1203 + pos = curOpt->backPrev2; 18.1204 + state = kRepNextStates[state]; 18.1205 + } 18.1206 + else 18.1207 + { 18.1208 + pos = curOpt->backPrev; 18.1209 + if (pos < LZMA_NUM_REPS) 18.1210 + state = kRepNextStates[state]; 18.1211 + else 18.1212 + state = kMatchNextStates[state]; 18.1213 + } 18.1214 + prevOpt = &p->opt[posPrev]; 18.1215 + if (pos < LZMA_NUM_REPS) 18.1216 + { 18.1217 + UInt32 i; 18.1218 + reps[0] = prevOpt->backs[pos]; 18.1219 + for (i = 1; i <= pos; i++) 18.1220 + reps[i] = prevOpt->backs[i - 1]; 18.1221 + for (; i < LZMA_NUM_REPS; i++) 18.1222 + reps[i] = prevOpt->backs[i]; 18.1223 + } 18.1224 + else 18.1225 + { 18.1226 + UInt32 i; 18.1227 + reps[0] = (pos - LZMA_NUM_REPS); 18.1228 + for (i = 1; i < LZMA_NUM_REPS; i++) 18.1229 + reps[i] = prevOpt->backs[i - 1]; 18.1230 + } 18.1231 + } 18.1232 + curOpt->state = (CState)state; 18.1233 + 18.1234 + curOpt->backs[0] = reps[0]; 18.1235 + curOpt->backs[1] = reps[1]; 18.1236 + curOpt->backs[2] = reps[2]; 18.1237 + curOpt->backs[3] = reps[3]; 18.1238 + 18.1239 + curPrice = curOpt->price; 18.1240 + nextIsChar = False; 18.1241 + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; 18.1242 + curByte = *data; 18.1243 + matchByte = *(data - (reps[0] + 1)); 18.1244 + 18.1245 + posState = (position & p->pbMask); 18.1246 + 18.1247 + curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); 18.1248 + { 18.1249 + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); 18.1250 + curAnd1Price += 18.1251 + (!IsCharState(state) ? 18.1252 + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : 18.1253 + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); 18.1254 + } 18.1255 + 18.1256 + nextOpt = &p->opt[cur + 1]; 18.1257 + 18.1258 + if (curAnd1Price < nextOpt->price) 18.1259 + { 18.1260 + nextOpt->price = curAnd1Price; 18.1261 + nextOpt->posPrev = cur; 18.1262 + MakeAsChar(nextOpt); 18.1263 + nextIsChar = True; 18.1264 + } 18.1265 + 18.1266 + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); 18.1267 + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); 18.1268 + 18.1269 + if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) 18.1270 + { 18.1271 + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); 18.1272 + if (shortRepPrice <= nextOpt->price) 18.1273 + { 18.1274 + nextOpt->price = shortRepPrice; 18.1275 + nextOpt->posPrev = cur; 18.1276 + MakeAsShortRep(nextOpt); 18.1277 + nextIsChar = True; 18.1278 + } 18.1279 + } 18.1280 + numAvailFull = p->numAvail; 18.1281 + { 18.1282 + UInt32 temp = kNumOpts - 1 - cur; 18.1283 + if (temp < numAvailFull) 18.1284 + numAvailFull = temp; 18.1285 + } 18.1286 + 18.1287 + if (numAvailFull < 2) 18.1288 + continue; 18.1289 + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); 18.1290 + 18.1291 + if (!nextIsChar && matchByte != curByte) /* speed optimization */ 18.1292 + { 18.1293 + /* try Literal + rep0 */ 18.1294 + UInt32 temp; 18.1295 + UInt32 lenTest2; 18.1296 + const Byte *data2 = data - (reps[0] + 1); 18.1297 + UInt32 limit = p->numFastBytes + 1; 18.1298 + if (limit > numAvailFull) 18.1299 + limit = numAvailFull; 18.1300 + 18.1301 + for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); 18.1302 + lenTest2 = temp - 1; 18.1303 + if (lenTest2 >= 2) 18.1304 + { 18.1305 + UInt32 state2 = kLiteralNextStates[state]; 18.1306 + UInt32 posStateNext = (position + 1) & p->pbMask; 18.1307 + UInt32 nextRepMatchPrice = curAnd1Price + 18.1308 + GET_PRICE_1(p->isMatch[state2][posStateNext]) + 18.1309 + GET_PRICE_1(p->isRep[state2]); 18.1310 + /* for (; lenTest2 >= 2; lenTest2--) */ 18.1311 + { 18.1312 + UInt32 curAndLenPrice; 18.1313 + COptimal *opt; 18.1314 + UInt32 offset = cur + 1 + lenTest2; 18.1315 + while (lenEnd < offset) 18.1316 + p->opt[++lenEnd].price = kInfinityPrice; 18.1317 + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); 18.1318 + opt = &p->opt[offset]; 18.1319 + if (curAndLenPrice < opt->price) 18.1320 + { 18.1321 + opt->price = curAndLenPrice; 18.1322 + opt->posPrev = cur + 1; 18.1323 + opt->backPrev = 0; 18.1324 + opt->prev1IsChar = True; 18.1325 + opt->prev2 = False; 18.1326 + } 18.1327 + } 18.1328 + } 18.1329 + } 18.1330 + 18.1331 + startLen = 2; /* speed optimization */ 18.1332 + { 18.1333 + UInt32 repIndex; 18.1334 + for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) 18.1335 + { 18.1336 + UInt32 lenTest; 18.1337 + UInt32 lenTestTemp; 18.1338 + UInt32 price; 18.1339 + const Byte *data2 = data - (reps[repIndex] + 1); 18.1340 + if (data[0] != data2[0] || data[1] != data2[1]) 18.1341 + continue; 18.1342 + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); 18.1343 + while (lenEnd < cur + lenTest) 18.1344 + p->opt[++lenEnd].price = kInfinityPrice; 18.1345 + lenTestTemp = lenTest; 18.1346 + price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); 18.1347 + do 18.1348 + { 18.1349 + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; 18.1350 + COptimal *opt = &p->opt[cur + lenTest]; 18.1351 + if (curAndLenPrice < opt->price) 18.1352 + { 18.1353 + opt->price = curAndLenPrice; 18.1354 + opt->posPrev = cur; 18.1355 + opt->backPrev = repIndex; 18.1356 + opt->prev1IsChar = False; 18.1357 + } 18.1358 + } 18.1359 + while (--lenTest >= 2); 18.1360 + lenTest = lenTestTemp; 18.1361 + 18.1362 + if (repIndex == 0) 18.1363 + startLen = lenTest + 1; 18.1364 + 18.1365 + /* if (_maxMode) */ 18.1366 + { 18.1367 + UInt32 lenTest2 = lenTest + 1; 18.1368 + UInt32 limit = lenTest2 + p->numFastBytes; 18.1369 + UInt32 nextRepMatchPrice; 18.1370 + if (limit > numAvailFull) 18.1371 + limit = numAvailFull; 18.1372 + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); 18.1373 + lenTest2 -= lenTest + 1; 18.1374 + if (lenTest2 >= 2) 18.1375 + { 18.1376 + UInt32 state2 = kRepNextStates[state]; 18.1377 + UInt32 posStateNext = (position + lenTest) & p->pbMask; 18.1378 + UInt32 curAndLenCharPrice = 18.1379 + price + p->repLenEnc.prices[posState][lenTest - 2] + 18.1380 + GET_PRICE_0(p->isMatch[state2][posStateNext]) + 18.1381 + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), 18.1382 + data[lenTest], data2[lenTest], p->ProbPrices); 18.1383 + state2 = kLiteralNextStates[state2]; 18.1384 + posStateNext = (position + lenTest + 1) & p->pbMask; 18.1385 + nextRepMatchPrice = curAndLenCharPrice + 18.1386 + GET_PRICE_1(p->isMatch[state2][posStateNext]) + 18.1387 + GET_PRICE_1(p->isRep[state2]); 18.1388 + 18.1389 + /* for (; lenTest2 >= 2; lenTest2--) */ 18.1390 + { 18.1391 + UInt32 curAndLenPrice; 18.1392 + COptimal *opt; 18.1393 + UInt32 offset = cur + lenTest + 1 + lenTest2; 18.1394 + while (lenEnd < offset) 18.1395 + p->opt[++lenEnd].price = kInfinityPrice; 18.1396 + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); 18.1397 + opt = &p->opt[offset]; 18.1398 + if (curAndLenPrice < opt->price) 18.1399 + { 18.1400 + opt->price = curAndLenPrice; 18.1401 + opt->posPrev = cur + lenTest + 1; 18.1402 + opt->backPrev = 0; 18.1403 + opt->prev1IsChar = True; 18.1404 + opt->prev2 = True; 18.1405 + opt->posPrev2 = cur; 18.1406 + opt->backPrev2 = repIndex; 18.1407 + } 18.1408 + } 18.1409 + } 18.1410 + } 18.1411 + } 18.1412 + } 18.1413 + /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ 18.1414 + if (newLen > numAvail) 18.1415 + { 18.1416 + newLen = numAvail; 18.1417 + for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); 18.1418 + matches[numPairs] = newLen; 18.1419 + numPairs += 2; 18.1420 + } 18.1421 + if (newLen >= startLen) 18.1422 + { 18.1423 + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); 18.1424 + UInt32 offs, curBack, posSlot; 18.1425 + UInt32 lenTest; 18.1426 + while (lenEnd < cur + newLen) 18.1427 + p->opt[++lenEnd].price = kInfinityPrice; 18.1428 + 18.1429 + offs = 0; 18.1430 + while (startLen > matches[offs]) 18.1431 + offs += 2; 18.1432 + curBack = matches[offs + 1]; 18.1433 + GetPosSlot2(curBack, posSlot); 18.1434 + for (lenTest = /*2*/ startLen; ; lenTest++) 18.1435 + { 18.1436 + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; 18.1437 + UInt32 lenToPosState = GetLenToPosState(lenTest); 18.1438 + COptimal *opt; 18.1439 + if (curBack < kNumFullDistances) 18.1440 + curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; 18.1441 + else 18.1442 + curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; 18.1443 + 18.1444 + opt = &p->opt[cur + lenTest]; 18.1445 + if (curAndLenPrice < opt->price) 18.1446 + { 18.1447 + opt->price = curAndLenPrice; 18.1448 + opt->posPrev = cur; 18.1449 + opt->backPrev = curBack + LZMA_NUM_REPS; 18.1450 + opt->prev1IsChar = False; 18.1451 + } 18.1452 + 18.1453 + if (/*_maxMode && */lenTest == matches[offs]) 18.1454 + { 18.1455 + /* Try Match + Literal + Rep0 */ 18.1456 + const Byte *data2 = data - (curBack + 1); 18.1457 + UInt32 lenTest2 = lenTest + 1; 18.1458 + UInt32 limit = lenTest2 + p->numFastBytes; 18.1459 + UInt32 nextRepMatchPrice; 18.1460 + if (limit > numAvailFull) 18.1461 + limit = numAvailFull; 18.1462 + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); 18.1463 + lenTest2 -= lenTest + 1; 18.1464 + if (lenTest2 >= 2) 18.1465 + { 18.1466 + UInt32 state2 = kMatchNextStates[state]; 18.1467 + UInt32 posStateNext = (position + lenTest) & p->pbMask; 18.1468 + UInt32 curAndLenCharPrice = curAndLenPrice + 18.1469 + GET_PRICE_0(p->isMatch[state2][posStateNext]) + 18.1470 + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), 18.1471 + data[lenTest], data2[lenTest], p->ProbPrices); 18.1472 + state2 = kLiteralNextStates[state2]; 18.1473 + posStateNext = (posStateNext + 1) & p->pbMask; 18.1474 + nextRepMatchPrice = curAndLenCharPrice + 18.1475 + GET_PRICE_1(p->isMatch[state2][posStateNext]) + 18.1476 + GET_PRICE_1(p->isRep[state2]); 18.1477 + 18.1478 + /* for (; lenTest2 >= 2; lenTest2--) */ 18.1479 + { 18.1480 + UInt32 offset = cur + lenTest + 1 + lenTest2; 18.1481 + UInt32 curAndLenPrice; 18.1482 + COptimal *opt; 18.1483 + while (lenEnd < offset) 18.1484 + p->opt[++lenEnd].price = kInfinityPrice; 18.1485 + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); 18.1486 + opt = &p->opt[offset]; 18.1487 + if (curAndLenPrice < opt->price) 18.1488 + { 18.1489 + opt->price = curAndLenPrice; 18.1490 + opt->posPrev = cur + lenTest + 1; 18.1491 + opt->backPrev = 0; 18.1492 + opt->prev1IsChar = True; 18.1493 + opt->prev2 = True; 18.1494 + opt->posPrev2 = cur; 18.1495 + opt->backPrev2 = curBack + LZMA_NUM_REPS; 18.1496 + } 18.1497 + } 18.1498 + } 18.1499 + offs += 2; 18.1500 + if (offs == numPairs) 18.1501 + break; 18.1502 + curBack = matches[offs + 1]; 18.1503 + if (curBack >= kNumFullDistances) 18.1504 + GetPosSlot2(curBack, posSlot); 18.1505 + } 18.1506 + } 18.1507 + } 18.1508 + } 18.1509 +} 18.1510 + 18.1511 +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) 18.1512 + 18.1513 +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) 18.1514 +{ 18.1515 + UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; 18.1516 + const Byte *data; 18.1517 + const UInt32 *matches; 18.1518 + 18.1519 + if (p->additionalOffset == 0) 18.1520 + mainLen = ReadMatchDistances(p, &numPairs); 18.1521 + else 18.1522 + { 18.1523 + mainLen = p->longestMatchLength; 18.1524 + numPairs = p->numPairs; 18.1525 + } 18.1526 + 18.1527 + numAvail = p->numAvail; 18.1528 + *backRes = (UInt32)-1; 18.1529 + if (numAvail < 2) 18.1530 + return 1; 18.1531 + if (numAvail > LZMA_MATCH_LEN_MAX) 18.1532 + numAvail = LZMA_MATCH_LEN_MAX; 18.1533 + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; 18.1534 + 18.1535 + repLen = repIndex = 0; 18.1536 + for (i = 0; i < LZMA_NUM_REPS; i++) 18.1537 + { 18.1538 + UInt32 len; 18.1539 + const Byte *data2 = data - (p->reps[i] + 1); 18.1540 + if (data[0] != data2[0] || data[1] != data2[1]) 18.1541 + continue; 18.1542 + for (len = 2; len < numAvail && data[len] == data2[len]; len++); 18.1543 + if (len >= p->numFastBytes) 18.1544 + { 18.1545 + *backRes = i; 18.1546 + MovePos(p, len - 1); 18.1547 + return len; 18.1548 + } 18.1549 + if (len > repLen) 18.1550 + { 18.1551 + repIndex = i; 18.1552 + repLen = len; 18.1553 + } 18.1554 + } 18.1555 + 18.1556 + matches = p->matches; 18.1557 + if (mainLen >= p->numFastBytes) 18.1558 + { 18.1559 + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; 18.1560 + MovePos(p, mainLen - 1); 18.1561 + return mainLen; 18.1562 + } 18.1563 + 18.1564 + mainDist = 0; /* for GCC */ 18.1565 + if (mainLen >= 2) 18.1566 + { 18.1567 + mainDist = matches[numPairs - 1]; 18.1568 + while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) 18.1569 + { 18.1570 + if (!ChangePair(matches[numPairs - 3], mainDist)) 18.1571 + break; 18.1572 + numPairs -= 2; 18.1573 + mainLen = matches[numPairs - 2]; 18.1574 + mainDist = matches[numPairs - 1]; 18.1575 + } 18.1576 + if (mainLen == 2 && mainDist >= 0x80) 18.1577 + mainLen = 1; 18.1578 + } 18.1579 + 18.1580 + if (repLen >= 2 && ( 18.1581 + (repLen + 1 >= mainLen) || 18.1582 + (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || 18.1583 + (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) 18.1584 + { 18.1585 + *backRes = repIndex; 18.1586 + MovePos(p, repLen - 1); 18.1587 + return repLen; 18.1588 + } 18.1589 + 18.1590 + if (mainLen < 2 || numAvail <= 2) 18.1591 + return 1; 18.1592 + 18.1593 + p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); 18.1594 + if (p->longestMatchLength >= 2) 18.1595 + { 18.1596 + UInt32 newDistance = matches[p->numPairs - 1]; 18.1597 + if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || 18.1598 + (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || 18.1599 + (p->longestMatchLength > mainLen + 1) || 18.1600 + (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) 18.1601 + return 1; 18.1602 + } 18.1603 + 18.1604 + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; 18.1605 + for (i = 0; i < LZMA_NUM_REPS; i++) 18.1606 + { 18.1607 + UInt32 len, limit; 18.1608 + const Byte *data2 = data - (p->reps[i] + 1); 18.1609 + if (data[0] != data2[0] || data[1] != data2[1]) 18.1610 + continue; 18.1611 + limit = mainLen - 1; 18.1612 + for (len = 2; len < limit && data[len] == data2[len]; len++); 18.1613 + if (len >= limit) 18.1614 + return 1; 18.1615 + } 18.1616 + *backRes = mainDist + LZMA_NUM_REPS; 18.1617 + MovePos(p, mainLen - 2); 18.1618 + return mainLen; 18.1619 +} 18.1620 + 18.1621 +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) 18.1622 +{ 18.1623 + UInt32 len; 18.1624 + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); 18.1625 + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); 18.1626 + p->state = kMatchNextStates[p->state]; 18.1627 + len = LZMA_MATCH_LEN_MIN; 18.1628 + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); 18.1629 + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); 18.1630 + RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); 18.1631 + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); 18.1632 +} 18.1633 + 18.1634 +static SRes CheckErrors(CLzmaEnc *p) 18.1635 +{ 18.1636 + if (p->result != SZ_OK) 18.1637 + return p->result; 18.1638 + if (p->rc.res != SZ_OK) 18.1639 + p->result = SZ_ERROR_WRITE; 18.1640 + if (p->matchFinderBase.result != SZ_OK) 18.1641 + p->result = SZ_ERROR_READ; 18.1642 + if (p->result != SZ_OK) 18.1643 + p->finished = True; 18.1644 + return p->result; 18.1645 +} 18.1646 + 18.1647 +static SRes Flush(CLzmaEnc *p, UInt32 nowPos) 18.1648 +{ 18.1649 + /* ReleaseMFStream(); */ 18.1650 + p->finished = True; 18.1651 + if (p->writeEndMark) 18.1652 + WriteEndMarker(p, nowPos & p->pbMask); 18.1653 + RangeEnc_FlushData(&p->rc); 18.1654 + RangeEnc_FlushStream(&p->rc); 18.1655 + return CheckErrors(p); 18.1656 +} 18.1657 + 18.1658 +static void FillAlignPrices(CLzmaEnc *p) 18.1659 +{ 18.1660 + UInt32 i; 18.1661 + for (i = 0; i < kAlignTableSize; i++) 18.1662 + p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); 18.1663 + p->alignPriceCount = 0; 18.1664 +} 18.1665 + 18.1666 +static void FillDistancesPrices(CLzmaEnc *p) 18.1667 +{ 18.1668 + UInt32 tempPrices[kNumFullDistances]; 18.1669 + UInt32 i, lenToPosState; 18.1670 + for (i = kStartPosModelIndex; i < kNumFullDistances; i++) 18.1671 + { 18.1672 + UInt32 posSlot = GetPosSlot1(i); 18.1673 + UInt32 footerBits = ((posSlot >> 1) - 1); 18.1674 + UInt32 base = ((2 | (posSlot & 1)) << footerBits); 18.1675 + tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); 18.1676 + } 18.1677 + 18.1678 + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) 18.1679 + { 18.1680 + UInt32 posSlot; 18.1681 + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; 18.1682 + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; 18.1683 + for (posSlot = 0; posSlot < p->distTableSize; posSlot++) 18.1684 + posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); 18.1685 + for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) 18.1686 + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); 18.1687 + 18.1688 + { 18.1689 + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; 18.1690 + UInt32 i; 18.1691 + for (i = 0; i < kStartPosModelIndex; i++) 18.1692 + distancesPrices[i] = posSlotPrices[i]; 18.1693 + for (; i < kNumFullDistances; i++) 18.1694 + distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; 18.1695 + } 18.1696 + } 18.1697 + p->matchPriceCount = 0; 18.1698 +} 18.1699 + 18.1700 +void LzmaEnc_Construct(CLzmaEnc *p) 18.1701 +{ 18.1702 + RangeEnc_Construct(&p->rc); 18.1703 + MatchFinder_Construct(&p->matchFinderBase); 18.1704 + #ifdef COMPRESS_MF_MT 18.1705 + MatchFinderMt_Construct(&p->matchFinderMt); 18.1706 + p->matchFinderMt.MatchFinder = &p->matchFinderBase; 18.1707 + #endif 18.1708 + 18.1709 + { 18.1710 + CLzmaEncProps props; 18.1711 + LzmaEncProps_Init(&props); 18.1712 + LzmaEnc_SetProps(p, &props); 18.1713 + } 18.1714 + 18.1715 + #ifndef LZMA_LOG_BSR 18.1716 + LzmaEnc_FastPosInit(p->g_FastPos); 18.1717 + #endif 18.1718 + 18.1719 + LzmaEnc_InitPriceTables(p->ProbPrices); 18.1720 + p->litProbs = 0; 18.1721 + p->saveState.litProbs = 0; 18.1722 +} 18.1723 + 18.1724 +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) 18.1725 +{ 18.1726 + void *p; 18.1727 + p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); 18.1728 + if (p != 0) 18.1729 + LzmaEnc_Construct((CLzmaEnc *)p); 18.1730 + return p; 18.1731 +} 18.1732 + 18.1733 +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) 18.1734 +{ 18.1735 + alloc->Free(alloc, p->litProbs); 18.1736 + alloc->Free(alloc, p->saveState.litProbs); 18.1737 + p->litProbs = 0; 18.1738 + p->saveState.litProbs = 0; 18.1739 +} 18.1740 + 18.1741 +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) 18.1742 +{ 18.1743 + #ifdef COMPRESS_MF_MT 18.1744 + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); 18.1745 + #endif 18.1746 + MatchFinder_Free(&p->matchFinderBase, allocBig); 18.1747 + LzmaEnc_FreeLits(p, alloc); 18.1748 + RangeEnc_Free(&p->rc, alloc); 18.1749 +} 18.1750 + 18.1751 +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) 18.1752 +{ 18.1753 + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); 18.1754 + alloc->Free(alloc, p); 18.1755 +} 18.1756 + 18.1757 +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) 18.1758 +{ 18.1759 + UInt32 nowPos32, startPos32; 18.1760 + if (p->inStream != 0) 18.1761 + { 18.1762 + p->matchFinderBase.stream = p->inStream; 18.1763 + p->matchFinder.Init(p->matchFinderObj); 18.1764 + p->inStream = 0; 18.1765 + } 18.1766 + 18.1767 + if (p->finished) 18.1768 + return p->result; 18.1769 + RINOK(CheckErrors(p)); 18.1770 + 18.1771 + nowPos32 = (UInt32)p->nowPos64; 18.1772 + startPos32 = nowPos32; 18.1773 + 18.1774 + if (p->nowPos64 == 0) 18.1775 + { 18.1776 + UInt32 numPairs; 18.1777 + Byte curByte; 18.1778 + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) 18.1779 + return Flush(p, nowPos32); 18.1780 + ReadMatchDistances(p, &numPairs); 18.1781 + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); 18.1782 + p->state = kLiteralNextStates[p->state]; 18.1783 + curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); 18.1784 + LitEnc_Encode(&p->rc, p->litProbs, curByte); 18.1785 + p->additionalOffset--; 18.1786 + nowPos32++; 18.1787 + } 18.1788 + 18.1789 + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) 18.1790 + for (;;) 18.1791 + { 18.1792 + UInt32 pos, len, posState; 18.1793 + 18.1794 + if (p->fastMode) 18.1795 + len = GetOptimumFast(p, &pos); 18.1796 + else 18.1797 + len = GetOptimum(p, nowPos32, &pos); 18.1798 + 18.1799 + #ifdef SHOW_STAT2 18.1800 + printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); 18.1801 + #endif 18.1802 + 18.1803 + posState = nowPos32 & p->pbMask; 18.1804 + if (len == 1 && pos == (UInt32)-1) 18.1805 + { 18.1806 + Byte curByte; 18.1807 + CLzmaProb *probs; 18.1808 + const Byte *data; 18.1809 + 18.1810 + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); 18.1811 + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; 18.1812 + curByte = *data; 18.1813 + probs = LIT_PROBS(nowPos32, *(data - 1)); 18.1814 + if (IsCharState(p->state)) 18.1815 + LitEnc_Encode(&p->rc, probs, curByte); 18.1816 + else 18.1817 + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); 18.1818 + p->state = kLiteralNextStates[p->state]; 18.1819 + } 18.1820 + else 18.1821 + { 18.1822 + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); 18.1823 + if (pos < LZMA_NUM_REPS) 18.1824 + { 18.1825 + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); 18.1826 + if (pos == 0) 18.1827 + { 18.1828 + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); 18.1829 + RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); 18.1830 + } 18.1831 + else 18.1832 + { 18.1833 + UInt32 distance = p->reps[pos]; 18.1834 + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); 18.1835 + if (pos == 1) 18.1836 + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); 18.1837 + else 18.1838 + { 18.1839 + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); 18.1840 + RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); 18.1841 + if (pos == 3) 18.1842 + p->reps[3] = p->reps[2]; 18.1843 + p->reps[2] = p->reps[1]; 18.1844 + } 18.1845 + p->reps[1] = p->reps[0]; 18.1846 + p->reps[0] = distance; 18.1847 + } 18.1848 + if (len == 1) 18.1849 + p->state = kShortRepNextStates[p->state]; 18.1850 + else 18.1851 + { 18.1852 + LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); 18.1853 + p->state = kRepNextStates[p->state]; 18.1854 + } 18.1855 + } 18.1856 + else 18.1857 + { 18.1858 + UInt32 posSlot; 18.1859 + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); 18.1860 + p->state = kMatchNextStates[p->state]; 18.1861 + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); 18.1862 + pos -= LZMA_NUM_REPS; 18.1863 + GetPosSlot(pos, posSlot); 18.1864 + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); 18.1865 + 18.1866 + if (posSlot >= kStartPosModelIndex) 18.1867 + { 18.1868 + UInt32 footerBits = ((posSlot >> 1) - 1); 18.1869 + UInt32 base = ((2 | (posSlot & 1)) << footerBits); 18.1870 + UInt32 posReduced = pos - base; 18.1871 + 18.1872 + if (posSlot < kEndPosModelIndex) 18.1873 + RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); 18.1874 + else 18.1875 + { 18.1876 + RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); 18.1877 + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); 18.1878 + p->alignPriceCount++; 18.1879 + } 18.1880 + } 18.1881 + p->reps[3] = p->reps[2]; 18.1882 + p->reps[2] = p->reps[1]; 18.1883 + p->reps[1] = p->reps[0]; 18.1884 + p->reps[0] = pos; 18.1885 + p->matchPriceCount++; 18.1886 + } 18.1887 + } 18.1888 + p->additionalOffset -= len; 18.1889 + nowPos32 += len; 18.1890 + if (p->additionalOffset == 0) 18.1891 + { 18.1892 + UInt32 processed; 18.1893 + if (!p->fastMode) 18.1894 + { 18.1895 + if (p->matchPriceCount >= (1 << 7)) 18.1896 + FillDistancesPrices(p); 18.1897 + if (p->alignPriceCount >= kAlignTableSize) 18.1898 + FillAlignPrices(p); 18.1899 + } 18.1900 + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) 18.1901 + break; 18.1902 + processed = nowPos32 - startPos32; 18.1903 + if (useLimits) 18.1904 + { 18.1905 + if (processed + kNumOpts + 300 >= maxUnpackSize || 18.1906 + RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) 18.1907 + break; 18.1908 + } 18.1909 + else if (processed >= (1 << 15)) 18.1910 + { 18.1911 + p->nowPos64 += nowPos32 - startPos32; 18.1912 + return CheckErrors(p); 18.1913 + } 18.1914 + } 18.1915 + } 18.1916 + p->nowPos64 += nowPos32 - startPos32; 18.1917 + return Flush(p, nowPos32); 18.1918 +} 18.1919 + 18.1920 +#define kBigHashDicLimit ((UInt32)1 << 24) 18.1921 + 18.1922 +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) 18.1923 +{ 18.1924 + UInt32 beforeSize = kNumOpts; 18.1925 + Bool btMode; 18.1926 + if (!RangeEnc_Alloc(&p->rc, alloc)) 18.1927 + return SZ_ERROR_MEM; 18.1928 + btMode = (p->matchFinderBase.btMode != 0); 18.1929 + #ifdef COMPRESS_MF_MT 18.1930 + p->mtMode = (p->multiThread && !p->fastMode && btMode); 18.1931 + #endif 18.1932 + 18.1933 + { 18.1934 + unsigned lclp = p->lc + p->lp; 18.1935 + if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) 18.1936 + { 18.1937 + LzmaEnc_FreeLits(p, alloc); 18.1938 + p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); 18.1939 + p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); 18.1940 + if (p->litProbs == 0 || p->saveState.litProbs == 0) 18.1941 + { 18.1942 + LzmaEnc_FreeLits(p, alloc); 18.1943 + return SZ_ERROR_MEM; 18.1944 + } 18.1945 + p->lclp = lclp; 18.1946 + } 18.1947 + } 18.1948 + 18.1949 + p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); 18.1950 + 18.1951 + if (beforeSize + p->dictSize < keepWindowSize) 18.1952 + beforeSize = keepWindowSize - p->dictSize; 18.1953 + 18.1954 + #ifdef COMPRESS_MF_MT 18.1955 + if (p->mtMode) 18.1956 + { 18.1957 + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); 18.1958 + p->matchFinderObj = &p->matchFinderMt; 18.1959 + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); 18.1960 + } 18.1961 + else 18.1962 + #endif 18.1963 + { 18.1964 + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) 18.1965 + return SZ_ERROR_MEM; 18.1966 + p->matchFinderObj = &p->matchFinderBase; 18.1967 + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); 18.1968 + } 18.1969 + return SZ_OK; 18.1970 +} 18.1971 + 18.1972 +void LzmaEnc_Init(CLzmaEnc *p) 18.1973 +{ 18.1974 + UInt32 i; 18.1975 + p->state = 0; 18.1976 + for (i = 0 ; i < LZMA_NUM_REPS; i++) 18.1977 + p->reps[i] = 0; 18.1978 + 18.1979 + RangeEnc_Init(&p->rc); 18.1980 + 18.1981 + 18.1982 + for (i = 0; i < kNumStates; i++) 18.1983 + { 18.1984 + UInt32 j; 18.1985 + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) 18.1986 + { 18.1987 + p->isMatch[i][j] = kProbInitValue; 18.1988 + p->isRep0Long[i][j] = kProbInitValue; 18.1989 + } 18.1990 + p->isRep[i] = kProbInitValue; 18.1991 + p->isRepG0[i] = kProbInitValue; 18.1992 + p->isRepG1[i] = kProbInitValue; 18.1993 + p->isRepG2[i] = kProbInitValue; 18.1994 + } 18.1995 + 18.1996 + { 18.1997 + UInt32 num = 0x300 << (p->lp + p->lc); 18.1998 + for (i = 0; i < num; i++) 18.1999 + p->litProbs[i] = kProbInitValue; 18.2000 + } 18.2001 + 18.2002 + { 18.2003 + for (i = 0; i < kNumLenToPosStates; i++) 18.2004 + { 18.2005 + CLzmaProb *probs = p->posSlotEncoder[i]; 18.2006 + UInt32 j; 18.2007 + for (j = 0; j < (1 << kNumPosSlotBits); j++) 18.2008 + probs[j] = kProbInitValue; 18.2009 + } 18.2010 + } 18.2011 + { 18.2012 + for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) 18.2013 + p->posEncoders[i] = kProbInitValue; 18.2014 + } 18.2015 + 18.2016 + LenEnc_Init(&p->lenEnc.p); 18.2017 + LenEnc_Init(&p->repLenEnc.p); 18.2018 + 18.2019 + for (i = 0; i < (1 << kNumAlignBits); i++) 18.2020 + p->posAlignEncoder[i] = kProbInitValue; 18.2021 + 18.2022 + p->optimumEndIndex = 0; 18.2023 + p->optimumCurrentIndex = 0; 18.2024 + p->additionalOffset = 0; 18.2025 + 18.2026 + p->pbMask = (1 << p->pb) - 1; 18.2027 + p->lpMask = (1 << p->lp) - 1; 18.2028 +} 18.2029 + 18.2030 +void LzmaEnc_InitPrices(CLzmaEnc *p) 18.2031 +{ 18.2032 + if (!p->fastMode) 18.2033 + { 18.2034 + FillDistancesPrices(p); 18.2035 + FillAlignPrices(p); 18.2036 + } 18.2037 + 18.2038 + p->lenEnc.tableSize = 18.2039 + p->repLenEnc.tableSize = 18.2040 + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; 18.2041 + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); 18.2042 + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); 18.2043 +} 18.2044 + 18.2045 +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) 18.2046 +{ 18.2047 + UInt32 i; 18.2048 + for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) 18.2049 + if (p->dictSize <= ((UInt32)1 << i)) 18.2050 + break; 18.2051 + p->distTableSize = i * 2; 18.2052 + 18.2053 + p->finished = False; 18.2054 + p->result = SZ_OK; 18.2055 + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); 18.2056 + LzmaEnc_Init(p); 18.2057 + LzmaEnc_InitPrices(p); 18.2058 + p->nowPos64 = 0; 18.2059 + return SZ_OK; 18.2060 +} 18.2061 + 18.2062 +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream, 18.2063 + ISzAlloc *alloc, ISzAlloc *allocBig) 18.2064 +{ 18.2065 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2066 + p->inStream = inStream; 18.2067 + p->rc.outStream = outStream; 18.2068 + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); 18.2069 +} 18.2070 + 18.2071 +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, 18.2072 + ISeqInStream *inStream, UInt32 keepWindowSize, 18.2073 + ISzAlloc *alloc, ISzAlloc *allocBig) 18.2074 +{ 18.2075 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2076 + p->inStream = inStream; 18.2077 + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); 18.2078 +} 18.2079 + 18.2080 +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) 18.2081 +{ 18.2082 + p->seqBufInStream.funcTable.Read = MyRead; 18.2083 + p->seqBufInStream.data = src; 18.2084 + p->seqBufInStream.rem = srcLen; 18.2085 +} 18.2086 + 18.2087 +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, 18.2088 + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) 18.2089 +{ 18.2090 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2091 + LzmaEnc_SetInputBuf(p, src, srcLen); 18.2092 + p->inStream = &p->seqBufInStream.funcTable; 18.2093 + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); 18.2094 +} 18.2095 + 18.2096 +void LzmaEnc_Finish(CLzmaEncHandle pp) 18.2097 +{ 18.2098 + #ifdef COMPRESS_MF_MT 18.2099 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2100 + if (p->mtMode) 18.2101 + MatchFinderMt_ReleaseStream(&p->matchFinderMt); 18.2102 + #else 18.2103 + pp = pp; 18.2104 + #endif 18.2105 +} 18.2106 + 18.2107 +typedef struct _CSeqOutStreamBuf 18.2108 +{ 18.2109 + ISeqOutStream funcTable; 18.2110 + Byte *data; 18.2111 + SizeT rem; 18.2112 + Bool overflow; 18.2113 +} CSeqOutStreamBuf; 18.2114 + 18.2115 +static size_t MyWrite(void *pp, const void *data, size_t size) 18.2116 +{ 18.2117 + CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; 18.2118 + if (p->rem < size) 18.2119 + { 18.2120 + size = p->rem; 18.2121 + p->overflow = True; 18.2122 + } 18.2123 + memcpy(p->data, data, size); 18.2124 + p->rem -= size; 18.2125 + p->data += size; 18.2126 + return size; 18.2127 +} 18.2128 + 18.2129 + 18.2130 +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) 18.2131 +{ 18.2132 + const CLzmaEnc *p = (CLzmaEnc *)pp; 18.2133 + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); 18.2134 +} 18.2135 + 18.2136 +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) 18.2137 +{ 18.2138 + const CLzmaEnc *p = (CLzmaEnc *)pp; 18.2139 + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; 18.2140 +} 18.2141 + 18.2142 +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, 18.2143 + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) 18.2144 +{ 18.2145 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2146 + UInt64 nowPos64; 18.2147 + SRes res; 18.2148 + CSeqOutStreamBuf outStream; 18.2149 + 18.2150 + outStream.funcTable.Write = MyWrite; 18.2151 + outStream.data = dest; 18.2152 + outStream.rem = *destLen; 18.2153 + outStream.overflow = False; 18.2154 + 18.2155 + p->writeEndMark = False; 18.2156 + p->finished = False; 18.2157 + p->result = SZ_OK; 18.2158 + 18.2159 + if (reInit) 18.2160 + LzmaEnc_Init(p); 18.2161 + LzmaEnc_InitPrices(p); 18.2162 + nowPos64 = p->nowPos64; 18.2163 + RangeEnc_Init(&p->rc); 18.2164 + p->rc.outStream = &outStream.funcTable; 18.2165 + 18.2166 + res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); 18.2167 + 18.2168 + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); 18.2169 + *destLen -= outStream.rem; 18.2170 + if (outStream.overflow) 18.2171 + return SZ_ERROR_OUTPUT_EOF; 18.2172 + 18.2173 + return res; 18.2174 +} 18.2175 + 18.2176 +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, 18.2177 + ISzAlloc *alloc, ISzAlloc *allocBig) 18.2178 +{ 18.2179 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2180 + SRes res = SZ_OK; 18.2181 + 18.2182 + #ifdef COMPRESS_MF_MT 18.2183 + Byte allocaDummy[0x300]; 18.2184 + int i = 0; 18.2185 + for (i = 0; i < 16; i++) 18.2186 + allocaDummy[i] = (Byte)i; 18.2187 + #endif 18.2188 + 18.2189 + RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig)); 18.2190 + 18.2191 + for (;;) 18.2192 + { 18.2193 + res = LzmaEnc_CodeOneBlock(p, False, 0, 0); 18.2194 + if (res != SZ_OK || p->finished != 0) 18.2195 + break; 18.2196 + if (progress != 0) 18.2197 + { 18.2198 + res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); 18.2199 + if (res != SZ_OK) 18.2200 + { 18.2201 + res = SZ_ERROR_PROGRESS; 18.2202 + break; 18.2203 + } 18.2204 + } 18.2205 + } 18.2206 + LzmaEnc_Finish(pp); 18.2207 + return res; 18.2208 +} 18.2209 + 18.2210 +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) 18.2211 +{ 18.2212 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2213 + int i; 18.2214 + UInt32 dictSize = p->dictSize; 18.2215 + if (*size < LZMA_PROPS_SIZE) 18.2216 + return SZ_ERROR_PARAM; 18.2217 + *size = LZMA_PROPS_SIZE; 18.2218 + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); 18.2219 + 18.2220 + for (i = 11; i <= 30; i++) 18.2221 + { 18.2222 + if (dictSize <= ((UInt32)2 << i)) 18.2223 + { 18.2224 + dictSize = (2 << i); 18.2225 + break; 18.2226 + } 18.2227 + if (dictSize <= ((UInt32)3 << i)) 18.2228 + { 18.2229 + dictSize = (3 << i); 18.2230 + break; 18.2231 + } 18.2232 + } 18.2233 + 18.2234 + for (i = 0; i < 4; i++) 18.2235 + props[1 + i] = (Byte)(dictSize >> (8 * i)); 18.2236 + return SZ_OK; 18.2237 +} 18.2238 + 18.2239 +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, 18.2240 + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) 18.2241 +{ 18.2242 + SRes res; 18.2243 + CLzmaEnc *p = (CLzmaEnc *)pp; 18.2244 + 18.2245 + CSeqOutStreamBuf outStream; 18.2246 + 18.2247 + LzmaEnc_SetInputBuf(p, src, srcLen); 18.2248 + 18.2249 + outStream.funcTable.Write = MyWrite; 18.2250 + outStream.data = dest; 18.2251 + outStream.rem = *destLen; 18.2252 + outStream.overflow = False; 18.2253 + 18.2254 + p->writeEndMark = writeEndMark; 18.2255 + res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable, 18.2256 + progress, alloc, allocBig); 18.2257 + 18.2258 + *destLen -= outStream.rem; 18.2259 + if (outStream.overflow) 18.2260 + return SZ_ERROR_OUTPUT_EOF; 18.2261 + return res; 18.2262 +} 18.2263 + 18.2264 +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, 18.2265 + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 18.2266 + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) 18.2267 +{ 18.2268 + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); 18.2269 + SRes res; 18.2270 + if (p == 0) 18.2271 + return SZ_ERROR_MEM; 18.2272 + 18.2273 + res = LzmaEnc_SetProps(p, props); 18.2274 + if (res == SZ_OK) 18.2275 + { 18.2276 + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); 18.2277 + if (res == SZ_OK) 18.2278 + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, 18.2279 + writeEndMark, progress, alloc, allocBig); 18.2280 + } 18.2281 + 18.2282 + LzmaEnc_Destroy(p, alloc, allocBig); 18.2283 + return res; 18.2284 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/libs/openctm/liblzma/LzmaEnc.h Thu Sep 26 04:47:05 2013 +0300 19.3 @@ -0,0 +1,72 @@ 19.4 +/* LzmaEnc.h -- LZMA Encoder 19.5 +2008-10-04 : Igor Pavlov : Public domain */ 19.6 + 19.7 +#ifndef __LZMAENC_H 19.8 +#define __LZMAENC_H 19.9 + 19.10 +#include "Types.h" 19.11 + 19.12 +#define LZMA_PROPS_SIZE 5 19.13 + 19.14 +typedef struct _CLzmaEncProps 19.15 +{ 19.16 + int level; /* 0 <= level <= 9 */ 19.17 + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version 19.18 + (1 << 12) <= dictSize <= (1 << 30) for 64-bit version 19.19 + default = (1 << 24) */ 19.20 + int lc; /* 0 <= lc <= 8, default = 3 */ 19.21 + int lp; /* 0 <= lp <= 4, default = 0 */ 19.22 + int pb; /* 0 <= pb <= 4, default = 2 */ 19.23 + int algo; /* 0 - fast, 1 - normal, default = 1 */ 19.24 + int fb; /* 5 <= fb <= 273, default = 32 */ 19.25 + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ 19.26 + int numHashBytes; /* 2, 3 or 4, default = 4 */ 19.27 + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ 19.28 + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ 19.29 + int numThreads; /* 1 or 2, default = 2 */ 19.30 +} CLzmaEncProps; 19.31 + 19.32 +void LzmaEncProps_Init(CLzmaEncProps *p); 19.33 +void LzmaEncProps_Normalize(CLzmaEncProps *p); 19.34 +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); 19.35 + 19.36 + 19.37 +/* ---------- CLzmaEncHandle Interface ---------- */ 19.38 + 19.39 +/* LzmaEnc_* functions can return the following exit codes: 19.40 +Returns: 19.41 + SZ_OK - OK 19.42 + SZ_ERROR_MEM - Memory allocation error 19.43 + SZ_ERROR_PARAM - Incorrect paramater in props 19.44 + SZ_ERROR_WRITE - Write callback error. 19.45 + SZ_ERROR_PROGRESS - some break from progress callback 19.46 + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) 19.47 +*/ 19.48 + 19.49 +typedef void * CLzmaEncHandle; 19.50 + 19.51 +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); 19.52 +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); 19.53 +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); 19.54 +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); 19.55 +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, 19.56 + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); 19.57 +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, 19.58 + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); 19.59 + 19.60 +/* ---------- One Call Interface ---------- */ 19.61 + 19.62 +/* LzmaEncode 19.63 +Return code: 19.64 + SZ_OK - OK 19.65 + SZ_ERROR_MEM - Memory allocation error 19.66 + SZ_ERROR_PARAM - Incorrect paramater 19.67 + SZ_ERROR_OUTPUT_EOF - output buffer overflow 19.68 + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) 19.69 +*/ 19.70 + 19.71 +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, 19.72 + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, 19.73 + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); 19.74 + 19.75 +#endif
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/libs/openctm/liblzma/LzmaLib.c Thu Sep 26 04:47:05 2013 +0300 20.3 @@ -0,0 +1,48 @@ 20.4 +/* LzmaLib.c -- LZMA library wrapper 20.5 +2008-08-05 20.6 +Igor Pavlov 20.7 +Public domain */ 20.8 + 20.9 +#include "LzmaEnc.h" 20.10 +#include "LzmaDec.h" 20.11 +#include "Alloc.h" 20.12 +#include "LzmaLib.h" 20.13 + 20.14 +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } 20.15 +static void SzFree(void *p, void *address) { p = p; MyFree(address); } 20.16 +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; 20.17 + 20.18 +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, 20.19 + unsigned char *outProps, size_t *outPropsSize, 20.20 + int level, /* 0 <= level <= 9, default = 5 */ 20.21 + unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ 20.22 + int lc, /* 0 <= lc <= 8, default = 3 */ 20.23 + int lp, /* 0 <= lp <= 4, default = 0 */ 20.24 + int pb, /* 0 <= pb <= 4, default = 2 */ 20.25 + int fb, /* 5 <= fb <= 273, default = 32 */ 20.26 + int numThreads, /* 1 or 2, default = 2 */ 20.27 + int algo /* 0 = fast, 1 = normal */ 20.28 +) 20.29 +{ 20.30 + CLzmaEncProps props; 20.31 + LzmaEncProps_Init(&props); 20.32 + props.level = level; 20.33 + props.dictSize = dictSize; 20.34 + props.lc = lc; 20.35 + props.lp = lp; 20.36 + props.pb = pb; 20.37 + props.fb = fb; 20.38 + props.numThreads = numThreads; 20.39 + props.algo = algo; 20.40 + 20.41 + return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, 20.42 + NULL, &g_Alloc, &g_Alloc); 20.43 +} 20.44 + 20.45 + 20.46 +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, 20.47 + const unsigned char *props, size_t propsSize) 20.48 +{ 20.49 + ELzmaStatus status; 20.50 + return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); 20.51 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/libs/openctm/liblzma/LzmaLib.h Thu Sep 26 04:47:05 2013 +0300 21.3 @@ -0,0 +1,136 @@ 21.4 +/* LzmaLib.h -- LZMA library interface 21.5 +2008-08-05 21.6 +Igor Pavlov 21.7 +Public domain */ 21.8 + 21.9 +#ifndef __LZMALIB_H 21.10 +#define __LZMALIB_H 21.11 + 21.12 +#include "Types.h" 21.13 + 21.14 +#ifdef __cplusplus 21.15 + #define MY_EXTERN_C extern "C" 21.16 +#else 21.17 + #define MY_EXTERN_C extern 21.18 +#endif 21.19 + 21.20 +#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL 21.21 + 21.22 +#define LZMA_PROPS_SIZE 5 21.23 + 21.24 +/* 21.25 +RAM requirements for LZMA: 21.26 + for compression: (dictSize * 11.5 + 6 MB) + state_size 21.27 + for decompression: dictSize + state_size 21.28 + state_size = (4 + (1.5 << (lc + lp))) KB 21.29 + by default (lc=3, lp=0), state_size = 16 KB. 21.30 + 21.31 +LZMA properties (5 bytes) format 21.32 + Offset Size Description 21.33 + 0 1 lc, lp and pb in encoded form. 21.34 + 1 4 dictSize (little endian). 21.35 +*/ 21.36 + 21.37 +/* 21.38 +LzmaCompress 21.39 +------------ 21.40 + 21.41 +outPropsSize - 21.42 + In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. 21.43 + Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. 21.44 + 21.45 + LZMA Encoder will use defult values for any parameter, if it is 21.46 + -1 for any from: level, loc, lp, pb, fb, numThreads 21.47 + 0 for dictSize 21.48 + 21.49 +level - compression level: 0 <= level <= 9; 21.50 + 21.51 + level dictSize algo fb 21.52 + 0: 16 KB 0 32 21.53 + 1: 64 KB 0 32 21.54 + 2: 256 KB 0 32 21.55 + 3: 1 MB 0 32 21.56 + 4: 4 MB 0 32 21.57 + 5: 16 MB 1 32 21.58 + 6: 32 MB 1 32 21.59 + 7+: 64 MB 1 64 21.60 + 21.61 + The default value for "level" is 5. 21.62 + 21.63 + algo = 0 means fast method 21.64 + algo = 1 means normal method 21.65 + 21.66 +dictSize - The dictionary size in bytes. The maximum value is 21.67 + 128 MB = (1 << 27) bytes for 32-bit version 21.68 + 1 GB = (1 << 30) bytes for 64-bit version 21.69 + The default value is 16 MB = (1 << 24) bytes. 21.70 + It's recommended to use the dictionary that is larger than 4 KB and 21.71 + that can be calculated as (1 << N) or (3 << N) sizes. 21.72 + 21.73 +lc - The number of literal context bits (high bits of previous literal). 21.74 + It can be in the range from 0 to 8. The default value is 3. 21.75 + Sometimes lc=4 gives the gain for big files. 21.76 + 21.77 +lp - The number of literal pos bits (low bits of current position for literals). 21.78 + It can be in the range from 0 to 4. The default value is 0. 21.79 + The lp switch is intended for periodical data when the period is equal to 2^lp. 21.80 + For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's 21.81 + better to set lc=0, if you change lp switch. 21.82 + 21.83 +pb - The number of pos bits (low bits of current position). 21.84 + It can be in the range from 0 to 4. The default value is 2. 21.85 + The pb switch is intended for periodical data when the period is equal 2^pb. 21.86 + 21.87 +fb - Word size (the number of fast bytes). 21.88 + It can be in the range from 5 to 273. The default value is 32. 21.89 + Usually, a big number gives a little bit better compression ratio and 21.90 + slower compression process. 21.91 + 21.92 +numThreads - The number of thereads. 1 or 2. The default value is 2. 21.93 + Fast mode (algo = 0) can use only 1 thread. 21.94 + 21.95 +Out: 21.96 + destLen - processed output size 21.97 +Returns: 21.98 + SZ_OK - OK 21.99 + SZ_ERROR_MEM - Memory allocation error 21.100 + SZ_ERROR_PARAM - Incorrect paramater 21.101 + SZ_ERROR_OUTPUT_EOF - output buffer overflow 21.102 + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) 21.103 +*/ 21.104 + 21.105 +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, 21.106 + unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ 21.107 + int level, /* 0 <= level <= 9, default = 5 */ 21.108 + unsigned dictSize, /* default = (1 << 24) */ 21.109 + int lc, /* 0 <= lc <= 8, default = 3 */ 21.110 + int lp, /* 0 <= lp <= 4, default = 0 */ 21.111 + int pb, /* 0 <= pb <= 4, default = 2 */ 21.112 + int fb, /* 5 <= fb <= 273, default = 32 */ 21.113 + int numThreads, /* 1 or 2, default = 2 */ 21.114 + int algo /* 0 = fast, 1 = normal, default = 0 for level < 5, 1 for level >= 5 */ 21.115 + ); 21.116 + 21.117 +/* 21.118 +LzmaUncompress 21.119 +-------------- 21.120 +In: 21.121 + dest - output data 21.122 + destLen - output data size 21.123 + src - input data 21.124 + srcLen - input data size 21.125 +Out: 21.126 + destLen - processed output size 21.127 + srcLen - processed input size 21.128 +Returns: 21.129 + SZ_OK - OK 21.130 + SZ_ERROR_DATA - Data error 21.131 + SZ_ERROR_MEM - Memory allocation arror 21.132 + SZ_ERROR_UNSUPPORTED - Unsupported properties 21.133 + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) 21.134 +*/ 21.135 + 21.136 +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, 21.137 + const unsigned char *props, size_t propsSize); 21.138 + 21.139 +#endif
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/libs/openctm/liblzma/NameMangle.h Thu Sep 26 04:47:05 2013 +0300 22.3 @@ -0,0 +1,84 @@ 22.4 +/* NameMangle.h -- Name mangling to avoid linking conflicts 22.5 +2009-04-15 : Marcus Geelnard : Public domain */ 22.6 + 22.7 +#ifndef __7Z_NAMEMANGLE_H 22.8 +#define __7Z_NAMEMANGLE_H 22.9 + 22.10 +#ifdef LZMA_PREFIX_CTM 22.11 + 22.12 +/* Alloc.c */ 22.13 +#define MyAlloc _ctm_MyAlloc 22.14 +#define MyFree _ctm_MyFree 22.15 +#ifdef _WIN32 22.16 +#define MidAlloc _ctm_MidAlloc 22.17 +#define MidFree _ctm_MidFree 22.18 +#define SetLargePageSize _ctm_SetLargePageSize 22.19 +#define BigAlloc _ctm_BigAlloc 22.20 +#define BigFree _ctm_BigFree 22.21 +#endif /* _WIN32 */ 22.22 + 22.23 +/* LzFind.c */ 22.24 +#define MatchFinder_GetPointerToCurrentPos _ctm_MatchFinder_GetPointerToCurrentPos 22.25 +#define MatchFinder_GetIndexByte _ctm_MatchFinder_GetIndexByte 22.26 +#define MatchFinder_GetNumAvailableBytes _ctm_MatchFinder_GetNumAvailableBytes 22.27 +#define MatchFinder_ReduceOffsets _ctm_MatchFinder_ReduceOffsets 22.28 +#define MatchFinder_MoveBlock _ctm_MatchFinder_MoveBlock 22.29 +#define MatchFinder_NeedMove _ctm_MatchFinder_NeedMove 22.30 +#define MatchFinder_ReadIfRequired _ctm_MatchFinder_ReadIfRequired 22.31 +#define MatchFinder_Construct _ctm_MatchFinder_Construct 22.32 +#define MatchFinder_Free _ctm_MatchFinder_Free 22.33 +#define MatchFinder_Create _ctm_MatchFinder_Create 22.34 +#define MatchFinder_Init _ctm_MatchFinder_Init 22.35 +#define MatchFinder_Normalize3 _ctm_MatchFinder_Normalize3 22.36 +#define GetMatchesSpec1 _ctm_GetMatchesSpec1 22.37 +#define Bt3Zip_MatchFinder_GetMatches _ctm_Bt3Zip_MatchFinder_GetMatches 22.38 +#define Hc3Zip_MatchFinder_GetMatches _ctm_Hc3Zip_MatchFinder_GetMatches 22.39 +#define Bt3Zip_MatchFinder_Skip _ctm_Bt3Zip_MatchFinder_Skip 22.40 +#define Hc3Zip_MatchFinder_Skip _ctm_Hc3Zip_MatchFinder_Skip 22.41 +#define MatchFinder_CreateVTable _ctm_MatchFinder_CreateVTable 22.42 + 22.43 +/* LzmaDec.c */ 22.44 +#define LzmaDec_InitDicAndState _ctm_LzmaDec_InitDicAndState 22.45 +#define LzmaDec_Init _ctm_LzmaDec_Init 22.46 +#define LzmaDec_DecodeToDic _ctm_LzmaDec_DecodeToDic 22.47 +#define LzmaDec_DecodeToBuf _ctm_LzmaDec_DecodeToBuf 22.48 +#define LzmaDec_FreeProbs _ctm_LzmaDec_FreeProbs 22.49 +#define LzmaDec_Free _ctm_LzmaDec_Free 22.50 +#define LzmaProps_Decode _ctm_LzmaProps_Decode 22.51 +#define LzmaDec_AllocateProbs _ctm_LzmaDec_AllocateProbs 22.52 +#define LzmaDec_Allocate _ctm_LzmaDec_Allocate 22.53 +#define LzmaDecode _ctm_LzmaDecode 22.54 + 22.55 +/* LzmaEnc.c */ 22.56 +#define LzmaEncProps_Init _ctm_LzmaEncProps_Init 22.57 +#define LzmaEncProps_Normalize _ctm_LzmaEncProps_Normalize 22.58 +#define LzmaEncProps_GetDictSize _ctm_LzmaEncProps_GetDictSize 22.59 +#define LzmaEnc_FastPosInit _ctm_LzmaEnc_FastPosInit 22.60 +#define LzmaEnc_SaveState _ctm_LzmaEnc_SaveState 22.61 +#define LzmaEnc_RestoreState _ctm_LzmaEnc_RestoreState 22.62 +#define LzmaEnc_SetProps _ctm_LzmaEnc_SetProps 22.63 +#define LzmaEnc_InitPriceTables _ctm_LzmaEnc_InitPriceTables 22.64 +#define LzmaEnc_Construct _ctm_LzmaEnc_Construct 22.65 +#define LzmaEnc_Create _ctm_LzmaEnc_Create 22.66 +#define LzmaEnc_FreeLits _ctm_LzmaEnc_FreeLits 22.67 +#define LzmaEnc_Destruct _ctm_LzmaEnc_Destruct 22.68 +#define LzmaEnc_Destroy _ctm_LzmaEnc_Destroy 22.69 +#define LzmaEnc_Init _ctm_LzmaEnc_Init 22.70 +#define LzmaEnc_InitPrices _ctm_LzmaEnc_InitPrices 22.71 +#define LzmaEnc_PrepareForLzma2 _ctm_LzmaEnc_PrepareForLzma2 22.72 +#define LzmaEnc_MemPrepare _ctm_LzmaEnc_MemPrepare 22.73 +#define LzmaEnc_Finish _ctm_LzmaEnc_Finish 22.74 +#define LzmaEnc_GetNumAvailableBytes _ctm_LzmaEnc_GetNumAvailableBytes 22.75 +#define LzmaEnc_GetCurBuf _ctm_LzmaEnc_GetCurBuf 22.76 +#define LzmaEnc_CodeOneMemBlock _ctm_LzmaEnc_CodeOneMemBlock 22.77 +#define LzmaEnc_Encode _ctm_LzmaEnc_Encode 22.78 +#define LzmaEnc_WriteProperties _ctm_LzmaEnc_WriteProperties 22.79 +#define LzmaEnc_MemEncode _ctm_LzmaEnc_MemEncode 22.80 + 22.81 +/* LzmaLib.c */ 22.82 +#define LzmaCompress _ctm_LzmaCompress 22.83 +#define LzmaUncompress _ctm_LzmaUncompress 22.84 + 22.85 +#endif /* LZMA_PREFIX_CTM */ 22.86 + 22.87 +#endif /* __7Z_NAMEMANGLE_H */
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/libs/openctm/liblzma/Types.h Thu Sep 26 04:47:05 2013 +0300 23.3 @@ -0,0 +1,210 @@ 23.4 +/* Types.h -- Basic types 23.5 +2008-11-23 : Igor Pavlov : Public domain */ 23.6 + 23.7 +#ifndef __7Z_TYPES_H 23.8 +#define __7Z_TYPES_H 23.9 + 23.10 +#include <stddef.h> 23.11 + 23.12 +#ifdef _WIN32 23.13 +#include <windows.h> 23.14 +#endif 23.15 + 23.16 +#include "NameMangle.h" 23.17 + 23.18 +#define SZ_OK 0 23.19 + 23.20 +#define SZ_ERROR_DATA 1 23.21 +#define SZ_ERROR_MEM 2 23.22 +#define SZ_ERROR_CRC 3 23.23 +#define SZ_ERROR_UNSUPPORTED 4 23.24 +#define SZ_ERROR_PARAM 5 23.25 +#define SZ_ERROR_INPUT_EOF 6 23.26 +#define SZ_ERROR_OUTPUT_EOF 7 23.27 +#define SZ_ERROR_READ 8 23.28 +#define SZ_ERROR_WRITE 9 23.29 +#define SZ_ERROR_PROGRESS 10 23.30 +#define SZ_ERROR_FAIL 11 23.31 +#define SZ_ERROR_THREAD 12 23.32 + 23.33 +#define SZ_ERROR_ARCHIVE 16 23.34 +#define SZ_ERROR_NO_ARCHIVE 17 23.35 + 23.36 +typedef int SRes; 23.37 + 23.38 +#ifdef _WIN32 23.39 +typedef DWORD WRes; 23.40 +#else 23.41 +typedef int WRes; 23.42 +#endif 23.43 + 23.44 +#ifndef RINOK 23.45 +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } 23.46 +#endif 23.47 + 23.48 +typedef unsigned char Byte; 23.49 +typedef short Int16; 23.50 +typedef unsigned short UInt16; 23.51 + 23.52 +#ifdef _LZMA_UINT32_IS_ULONG 23.53 +typedef long Int32; 23.54 +typedef unsigned long UInt32; 23.55 +#else 23.56 +typedef int Int32; 23.57 +typedef unsigned int UInt32; 23.58 +#endif 23.59 + 23.60 +#ifdef _SZ_NO_INT_64 23.61 + 23.62 +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. 23.63 + NOTES: Some code will work incorrectly in that case! */ 23.64 + 23.65 +typedef long Int64; 23.66 +typedef unsigned long UInt64; 23.67 + 23.68 +#else 23.69 + 23.70 +#if defined(_MSC_VER) || defined(__BORLANDC__) 23.71 +typedef __int64 Int64; 23.72 +typedef unsigned __int64 UInt64; 23.73 +#else 23.74 +typedef long long int Int64; 23.75 +typedef unsigned long long int UInt64; 23.76 +#endif 23.77 + 23.78 +#endif 23.79 + 23.80 +#ifdef _LZMA_NO_SYSTEM_SIZE_T 23.81 +typedef UInt32 SizeT; 23.82 +#else 23.83 +typedef size_t SizeT; 23.84 +#endif 23.85 + 23.86 +typedef int Bool; 23.87 +#define True 1 23.88 +#define False 0 23.89 + 23.90 + 23.91 +#ifdef _MSC_VER 23.92 + 23.93 +#if _MSC_VER >= 1300 23.94 +#define MY_NO_INLINE __declspec(noinline) 23.95 +#else 23.96 +#define MY_NO_INLINE 23.97 +#endif 23.98 + 23.99 +#define MY_CDECL __cdecl 23.100 +#define MY_STD_CALL __stdcall 23.101 +#define MY_FAST_CALL MY_NO_INLINE __fastcall 23.102 + 23.103 +#else 23.104 + 23.105 +#define MY_CDECL 23.106 +#define MY_STD_CALL 23.107 +#define MY_FAST_CALL 23.108 + 23.109 +#endif 23.110 + 23.111 + 23.112 +/* The following interfaces use first parameter as pointer to structure */ 23.113 + 23.114 +typedef struct 23.115 +{ 23.116 + SRes (*Read)(void *p, void *buf, size_t *size); 23.117 + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 23.118 + (output(*size) < input(*size)) is allowed */ 23.119 +} ISeqInStream; 23.120 + 23.121 +/* it can return SZ_ERROR_INPUT_EOF */ 23.122 +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); 23.123 +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); 23.124 +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); 23.125 + 23.126 +typedef struct 23.127 +{ 23.128 + size_t (*Write)(void *p, const void *buf, size_t size); 23.129 + /* Returns: result - the number of actually written bytes. 23.130 + (result < size) means error */ 23.131 +} ISeqOutStream; 23.132 + 23.133 +typedef enum 23.134 +{ 23.135 + SZ_SEEK_SET = 0, 23.136 + SZ_SEEK_CUR = 1, 23.137 + SZ_SEEK_END = 2 23.138 +} ESzSeek; 23.139 + 23.140 +typedef struct 23.141 +{ 23.142 + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ 23.143 + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); 23.144 +} ISeekInStream; 23.145 + 23.146 +typedef struct 23.147 +{ 23.148 + SRes (*Look)(void *p, void **buf, size_t *size); 23.149 + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. 23.150 + (output(*size) > input(*size)) is not allowed 23.151 + (output(*size) < input(*size)) is allowed */ 23.152 + SRes (*Skip)(void *p, size_t offset); 23.153 + /* offset must be <= output(*size) of Look */ 23.154 + 23.155 + SRes (*Read)(void *p, void *buf, size_t *size); 23.156 + /* reads directly (without buffer). It's same as ISeqInStream::Read */ 23.157 + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); 23.158 +} ILookInStream; 23.159 + 23.160 +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); 23.161 +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); 23.162 + 23.163 +/* reads via ILookInStream::Read */ 23.164 +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); 23.165 +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); 23.166 + 23.167 +#define LookToRead_BUF_SIZE (1 << 14) 23.168 + 23.169 +typedef struct 23.170 +{ 23.171 + ILookInStream s; 23.172 + ISeekInStream *realStream; 23.173 + size_t pos; 23.174 + size_t size; 23.175 + Byte buf[LookToRead_BUF_SIZE]; 23.176 +} CLookToRead; 23.177 + 23.178 +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); 23.179 +void LookToRead_Init(CLookToRead *p); 23.180 + 23.181 +typedef struct 23.182 +{ 23.183 + ISeqInStream s; 23.184 + ILookInStream *realStream; 23.185 +} CSecToLook; 23.186 + 23.187 +void SecToLook_CreateVTable(CSecToLook *p); 23.188 + 23.189 +typedef struct 23.190 +{ 23.191 + ISeqInStream s; 23.192 + ILookInStream *realStream; 23.193 +} CSecToRead; 23.194 + 23.195 +void SecToRead_CreateVTable(CSecToRead *p); 23.196 + 23.197 +typedef struct 23.198 +{ 23.199 + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); 23.200 + /* Returns: result. (result != SZ_OK) means break. 23.201 + Value (UInt64)(Int64)-1 for size means unknown value. */ 23.202 +} ICompressProgress; 23.203 + 23.204 +typedef struct 23.205 +{ 23.206 + void *(*Alloc)(void *p, size_t size); 23.207 + void (*Free)(void *p, void *address); /* address can be 0 */ 23.208 +} ISzAlloc; 23.209 + 23.210 +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) 23.211 +#define IAlloc_Free(p, a) (p)->Free((p), a) 23.212 + 23.213 +#endif
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/libs/openctm/liblzma/readme.txt Thu Sep 26 04:47:05 2013 +0300 24.3 @@ -0,0 +1,7 @@ 24.4 +This is the C library implementation of LZMA compression/decompression by Igor Pavlov. 24.5 + 24.6 +Author: Igor Pavlov 24.7 +License: Public domain 24.8 +Version: 4.65 (2009-02-03) 24.9 + 24.10 +Some administrative adaptations for integration in OpenCTM were made by Marcus Geelnard.
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/libs/openctm/openctm.c Thu Sep 26 04:47:05 2013 +0300 25.3 @@ -0,0 +1,1423 @@ 25.4 +//----------------------------------------------------------------------------- 25.5 +// Product: OpenCTM 25.6 +// File: openctm.c 25.7 +// Description: API functions. 25.8 +//----------------------------------------------------------------------------- 25.9 +// Copyright (c) 2009-2010 Marcus Geelnard 25.10 +// 25.11 +// This software is provided 'as-is', without any express or implied 25.12 +// warranty. In no event will the authors be held liable for any damages 25.13 +// arising from the use of this software. 25.14 +// 25.15 +// Permission is granted to anyone to use this software for any purpose, 25.16 +// including commercial applications, and to alter it and redistribute it 25.17 +// freely, subject to the following restrictions: 25.18 +// 25.19 +// 1. The origin of this software must not be misrepresented; you must not 25.20 +// claim that you wrote the original software. If you use this software 25.21 +// in a product, an acknowledgment in the product documentation would be 25.22 +// appreciated but is not required. 25.23 +// 25.24 +// 2. Altered source versions must be plainly marked as such, and must not 25.25 +// be misrepresented as being the original software. 25.26 +// 25.27 +// 3. This notice may not be removed or altered from any source 25.28 +// distribution. 25.29 +//----------------------------------------------------------------------------- 25.30 + 25.31 +#include <stdlib.h> 25.32 +#include <string.h> 25.33 +#include <stdio.h> 25.34 +#include <math.h> 25.35 +#include "openctm.h" 25.36 +#include "internal.h" 25.37 + 25.38 + 25.39 +// The C99 macro isfinite() is not supported on all platforms (specifically, 25.40 +// MS Visual Studio does not support C99) 25.41 +#if !defined(isfinite) && defined(_MSC_VER) 25.42 + #include <float.h> 25.43 + #define isfinite(x) _finite(x) 25.44 +#endif 25.45 + 25.46 + 25.47 +//----------------------------------------------------------------------------- 25.48 +// _ctmFreeMapList() - Free a float map list. 25.49 +//----------------------------------------------------------------------------- 25.50 +static void _ctmFreeMapList(_CTMcontext * self, _CTMfloatmap * aMapList) 25.51 +{ 25.52 + _CTMfloatmap * map, * nextMap; 25.53 + map = aMapList; 25.54 + while(map) 25.55 + { 25.56 + // Free internally allocated array (if we are in import mode) 25.57 + if((self->mMode == CTM_IMPORT) && map->mValues) 25.58 + free(map->mValues); 25.59 + 25.60 + // Free map name 25.61 + if(map->mName) 25.62 + free(map->mName); 25.63 + 25.64 + // Free file name 25.65 + if(map->mFileName) 25.66 + free(map->mFileName); 25.67 + 25.68 + nextMap = map->mNext; 25.69 + free(map); 25.70 + map = nextMap; 25.71 + } 25.72 +} 25.73 + 25.74 +//----------------------------------------------------------------------------- 25.75 +// _ctmClearMesh() - Clear the mesh in a CTM context. 25.76 +//----------------------------------------------------------------------------- 25.77 +static void _ctmClearMesh(_CTMcontext * self) 25.78 +{ 25.79 + // Free internally allocated mesh arrays 25.80 + if(self->mMode == CTM_IMPORT) 25.81 + { 25.82 + if(self->mVertices) 25.83 + free(self->mVertices); 25.84 + if(self->mIndices) 25.85 + free(self->mIndices); 25.86 + if(self->mNormals) 25.87 + free(self->mNormals); 25.88 + } 25.89 + 25.90 + // Clear externally assigned mesh arrays 25.91 + self->mVertices = (CTMfloat *) 0; 25.92 + self->mVertexCount = 0; 25.93 + self->mIndices = (CTMuint *) 0; 25.94 + self->mTriangleCount = 0; 25.95 + self->mNormals = (CTMfloat *) 0; 25.96 + 25.97 + // Free UV coordinate map list 25.98 + _ctmFreeMapList(self, self->mUVMaps); 25.99 + self->mUVMaps = (_CTMfloatmap *) 0; 25.100 + self->mUVMapCount = 0; 25.101 + 25.102 + // Free attribute map list 25.103 + _ctmFreeMapList(self, self->mAttribMaps); 25.104 + self->mAttribMaps = (_CTMfloatmap *) 0; 25.105 + self->mAttribMapCount = 0; 25.106 +} 25.107 + 25.108 +//----------------------------------------------------------------------------- 25.109 +// _ctmCheckMeshIntegrity() - Check if a mesh is valid (i.e. is non-empty, and 25.110 +// contains valid data). 25.111 +//----------------------------------------------------------------------------- 25.112 + 25.113 +static CTMint _ctmCheckMeshIntegrity(_CTMcontext * self) 25.114 +{ 25.115 + CTMuint i; 25.116 + _CTMfloatmap * map; 25.117 + 25.118 + // Check that we have all the mandatory data 25.119 + if(!self->mVertices || !self->mIndices || (self->mVertexCount < 1) || 25.120 + (self->mTriangleCount < 1)) 25.121 + { 25.122 + return CTM_FALSE; 25.123 + } 25.124 + 25.125 + // Check that all indices are within range 25.126 + for(i = 0; i < (self->mTriangleCount * 3); ++ i) 25.127 + { 25.128 + if(self->mIndices[i] >= self->mVertexCount) 25.129 + { 25.130 + return CTM_FALSE; 25.131 + } 25.132 + } 25.133 + 25.134 + // Check that all vertices are finite (non-NaN, non-inf) 25.135 + for(i = 0; i < self->mVertexCount * 3; ++ i) 25.136 + { 25.137 + if(!isfinite(self->mVertices[i])) 25.138 + { 25.139 + return CTM_FALSE; 25.140 + } 25.141 + } 25.142 + 25.143 + // Check that all normals are finite (non-NaN, non-inf) 25.144 + if(self->mNormals) 25.145 + { 25.146 + for(i = 0; i < self->mVertexCount * 3; ++ i) 25.147 + { 25.148 + if(!isfinite(self->mNormals[i])) 25.149 + { 25.150 + return CTM_FALSE; 25.151 + } 25.152 + } 25.153 + } 25.154 + 25.155 + // Check that all UV maps are finite (non-NaN, non-inf) 25.156 + map = self->mUVMaps; 25.157 + while(map) 25.158 + { 25.159 + for(i = 0; i < self->mVertexCount * 2; ++ i) 25.160 + { 25.161 + if(!isfinite(map->mValues[i])) 25.162 + { 25.163 + return CTM_FALSE; 25.164 + } 25.165 + } 25.166 + map = map->mNext; 25.167 + } 25.168 + 25.169 + // Check that all attribute maps are finite (non-NaN, non-inf) 25.170 + map = self->mAttribMaps; 25.171 + while(map) 25.172 + { 25.173 + for(i = 0; i < self->mVertexCount * 4; ++ i) 25.174 + { 25.175 + if(!isfinite(map->mValues[i])) 25.176 + { 25.177 + return CTM_FALSE; 25.178 + } 25.179 + } 25.180 + map = map->mNext; 25.181 + } 25.182 + 25.183 + return CTM_TRUE; 25.184 +} 25.185 + 25.186 +//----------------------------------------------------------------------------- 25.187 +// ctmNewContext() 25.188 +//----------------------------------------------------------------------------- 25.189 +CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode) 25.190 +{ 25.191 + _CTMcontext * self; 25.192 + 25.193 + // Allocate memory for the new structure 25.194 + self = (_CTMcontext *) malloc(sizeof(_CTMcontext)); 25.195 + 25.196 + // Initialize structure (set null pointers and zero array lengths) 25.197 + memset(self, 0, sizeof(_CTMcontext)); 25.198 + self->mMode = aMode; 25.199 + self->mError = CTM_NONE; 25.200 + self->mMethod = CTM_METHOD_MG1; 25.201 + self->mCompressionLevel = 1; 25.202 + self->mVertexPrecision = 1.0f / 1024.0f; 25.203 + self->mNormalPrecision = 1.0f / 256.0f; 25.204 + 25.205 + return (CTMcontext) self; 25.206 +} 25.207 + 25.208 +//----------------------------------------------------------------------------- 25.209 +// ctmFreeContext() 25.210 +//----------------------------------------------------------------------------- 25.211 +CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext) 25.212 +{ 25.213 + _CTMcontext * self = (_CTMcontext *) aContext; 25.214 + if(!self) return; 25.215 + 25.216 + // Free all mesh resources 25.217 + _ctmClearMesh(self); 25.218 + 25.219 + // Free the file comment 25.220 + if(self->mFileComment) 25.221 + free(self->mFileComment); 25.222 + 25.223 + // Free the context 25.224 + free(self); 25.225 +} 25.226 + 25.227 +//----------------------------------------------------------------------------- 25.228 +// ctmGetError() 25.229 +//----------------------------------------------------------------------------- 25.230 +CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext) 25.231 +{ 25.232 + _CTMcontext * self = (_CTMcontext *) aContext; 25.233 + CTMenum err; 25.234 + 25.235 + if(!self) return CTM_INVALID_CONTEXT; 25.236 + 25.237 + // Get error code and reset error state 25.238 + err = self->mError; 25.239 + self->mError = CTM_NONE; 25.240 + return err; 25.241 +} 25.242 + 25.243 +//----------------------------------------------------------------------------- 25.244 +// ctmErrorString() 25.245 +//----------------------------------------------------------------------------- 25.246 +CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError) 25.247 +{ 25.248 + switch(aError) 25.249 + { 25.250 + case CTM_INVALID_CONTEXT: 25.251 + return "CTM_INVALID_CONTEXT"; 25.252 + case CTM_INVALID_ARGUMENT: 25.253 + return "CTM_INVALID_ARGUMENT"; 25.254 + case CTM_INVALID_OPERATION: 25.255 + return "CTM_INVALID_OPERATION"; 25.256 + case CTM_INVALID_MESH: 25.257 + return "CTM_INVALID_MESH"; 25.258 + case CTM_OUT_OF_MEMORY: 25.259 + return "CTM_OUT_OF_MEMORY"; 25.260 + case CTM_FILE_ERROR: 25.261 + return "CTM_FILE_ERROR"; 25.262 + case CTM_BAD_FORMAT: 25.263 + return "CTM_BAD_FORMAT"; 25.264 + case CTM_LZMA_ERROR: 25.265 + return "CTM_LZMA_ERROR"; 25.266 + case CTM_INTERNAL_ERROR: 25.267 + return "CTM_INTERNAL_ERROR"; 25.268 + case CTM_UNSUPPORTED_FORMAT_VERSION: 25.269 + return "CTM_UNSUPPORTED_FORMAT_VERSION"; 25.270 + default: 25.271 + return "Unknown error code"; 25.272 + } 25.273 +} 25.274 + 25.275 +//----------------------------------------------------------------------------- 25.276 +// ctmGetInteger() 25.277 +//----------------------------------------------------------------------------- 25.278 +CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty) 25.279 +{ 25.280 + _CTMcontext * self = (_CTMcontext *) aContext; 25.281 + if(!self) return 0; 25.282 + 25.283 + switch(aProperty) 25.284 + { 25.285 + case CTM_VERTEX_COUNT: 25.286 + return self->mVertexCount; 25.287 + 25.288 + case CTM_TRIANGLE_COUNT: 25.289 + return self->mTriangleCount; 25.290 + 25.291 + case CTM_UV_MAP_COUNT: 25.292 + return self->mUVMapCount; 25.293 + 25.294 + case CTM_ATTRIB_MAP_COUNT: 25.295 + return self->mAttribMapCount; 25.296 + 25.297 + case CTM_HAS_NORMALS: 25.298 + return self->mNormals ? CTM_TRUE : CTM_FALSE; 25.299 + 25.300 + case CTM_COMPRESSION_METHOD: 25.301 + return (CTMuint) self->mMethod; 25.302 + 25.303 + default: 25.304 + self->mError = CTM_INVALID_ARGUMENT; 25.305 + } 25.306 + 25.307 + return 0; 25.308 +} 25.309 + 25.310 +//----------------------------------------------------------------------------- 25.311 +// ctmGetFloat() 25.312 +//----------------------------------------------------------------------------- 25.313 +CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty) 25.314 +{ 25.315 + _CTMcontext * self = (_CTMcontext *) aContext; 25.316 + if(!self) return 0.0f; 25.317 + 25.318 + switch(aProperty) 25.319 + { 25.320 + case CTM_VERTEX_PRECISION: 25.321 + return self->mVertexPrecision; 25.322 + 25.323 + case CTM_NORMAL_PRECISION: 25.324 + return self->mNormalPrecision; 25.325 + 25.326 + default: 25.327 + self->mError = CTM_INVALID_ARGUMENT; 25.328 + } 25.329 + 25.330 + return 0.0f; 25.331 +} 25.332 + 25.333 +//----------------------------------------------------------------------------- 25.334 +// ctmGetIntegerArray() 25.335 +//----------------------------------------------------------------------------- 25.336 +CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext, 25.337 + CTMenum aProperty) 25.338 +{ 25.339 + _CTMcontext * self = (_CTMcontext *) aContext; 25.340 + if(!self) return (CTMuint *) 0; 25.341 + 25.342 + switch(aProperty) 25.343 + { 25.344 + case CTM_INDICES: 25.345 + return self->mIndices; 25.346 + 25.347 + default: 25.348 + self->mError = CTM_INVALID_ARGUMENT; 25.349 + } 25.350 + 25.351 + return (CTMuint *) 0; 25.352 +} 25.353 + 25.354 +//----------------------------------------------------------------------------- 25.355 +// ctmGetFloatArray() 25.356 +//----------------------------------------------------------------------------- 25.357 +CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext, 25.358 + CTMenum aProperty) 25.359 +{ 25.360 + _CTMcontext * self = (_CTMcontext *) aContext; 25.361 + _CTMfloatmap * map; 25.362 + CTMuint i; 25.363 + if(!self) return (CTMfloat *) 0; 25.364 + 25.365 + // Did the user request a UV map? 25.366 + if((aProperty >= CTM_UV_MAP_1) && 25.367 + ((CTMuint)(aProperty - CTM_UV_MAP_1) < self->mUVMapCount)) 25.368 + { 25.369 + map = self->mUVMaps; 25.370 + i = CTM_UV_MAP_1; 25.371 + while(map && (i != aProperty)) 25.372 + { 25.373 + map = map->mNext; 25.374 + ++ i; 25.375 + } 25.376 + if(!map) 25.377 + { 25.378 + self->mError = CTM_INTERNAL_ERROR; 25.379 + return (CTMfloat *) 0; 25.380 + } 25.381 + return map->mValues; 25.382 + } 25.383 + 25.384 + // Did the user request an attribute map? 25.385 + if((aProperty >= CTM_ATTRIB_MAP_1) && 25.386 + ((CTMuint)(aProperty - CTM_ATTRIB_MAP_1) < self->mAttribMapCount)) 25.387 + { 25.388 + map = self->mAttribMaps; 25.389 + i = CTM_ATTRIB_MAP_1; 25.390 + while(map && (i != aProperty)) 25.391 + { 25.392 + map = map->mNext; 25.393 + ++ i; 25.394 + } 25.395 + if(!map) 25.396 + { 25.397 + self->mError = CTM_INTERNAL_ERROR; 25.398 + return (CTMfloat *) 0; 25.399 + } 25.400 + return map->mValues; 25.401 + } 25.402 + 25.403 + switch(aProperty) 25.404 + { 25.405 + case CTM_VERTICES: 25.406 + return self->mVertices; 25.407 + 25.408 + case CTM_NORMALS: 25.409 + return self->mNormals; 25.410 + 25.411 + default: 25.412 + self->mError = CTM_INVALID_ARGUMENT; 25.413 + } 25.414 + 25.415 + return (CTMfloat *) 0; 25.416 +} 25.417 + 25.418 +//----------------------------------------------------------------------------- 25.419 +// ctmGetNamedUVMap() 25.420 +//----------------------------------------------------------------------------- 25.421 +CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext, 25.422 + const char * aName) 25.423 +{ 25.424 + _CTMcontext * self = (_CTMcontext *) aContext; 25.425 + _CTMfloatmap * map; 25.426 + CTMuint result; 25.427 + if(!self) return CTM_NONE; 25.428 + 25.429 + map = self->mUVMaps; 25.430 + result = CTM_UV_MAP_1; 25.431 + while(map && (strcmp(aName, map->mName) != 0)) 25.432 + { 25.433 + map = map->mNext; 25.434 + ++ result; 25.435 + } 25.436 + if(!map) 25.437 + { 25.438 + return CTM_NONE; 25.439 + } 25.440 + return result; 25.441 +} 25.442 + 25.443 +//----------------------------------------------------------------------------- 25.444 +// ctmGetUVMapString() 25.445 +//----------------------------------------------------------------------------- 25.446 +CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext, 25.447 + CTMenum aUVMap, CTMenum aProperty) 25.448 +{ 25.449 + _CTMcontext * self = (_CTMcontext *) aContext; 25.450 + _CTMfloatmap * map; 25.451 + CTMuint i; 25.452 + if(!self) return (const char *) 0; 25.453 + 25.454 + // Find the indicated map 25.455 + map = self->mUVMaps; 25.456 + i = CTM_UV_MAP_1; 25.457 + while(map && (i != aUVMap)) 25.458 + { 25.459 + ++ i; 25.460 + map = map->mNext; 25.461 + } 25.462 + if(!map) 25.463 + { 25.464 + self->mError = CTM_INVALID_ARGUMENT; 25.465 + return (const char *) 0; 25.466 + } 25.467 + 25.468 + // Get the requested string 25.469 + switch(aProperty) 25.470 + { 25.471 + case CTM_NAME: 25.472 + return (const char *) map->mName; 25.473 + 25.474 + case CTM_FILE_NAME: 25.475 + return (const char *) map->mFileName; 25.476 + 25.477 + default: 25.478 + self->mError = CTM_INVALID_ARGUMENT; 25.479 + } 25.480 + 25.481 + return (const char *) 0; 25.482 +} 25.483 + 25.484 +//----------------------------------------------------------------------------- 25.485 +// ctmGetUVMapFloat() 25.486 +//----------------------------------------------------------------------------- 25.487 +CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext, 25.488 + CTMenum aUVMap, CTMenum aProperty) 25.489 +{ 25.490 + _CTMcontext * self = (_CTMcontext *) aContext; 25.491 + _CTMfloatmap * map; 25.492 + CTMuint i; 25.493 + if(!self) return 0.0f; 25.494 + 25.495 + // Find the indicated map 25.496 + map = self->mUVMaps; 25.497 + i = CTM_UV_MAP_1; 25.498 + while(map && (i != aUVMap)) 25.499 + { 25.500 + ++ i; 25.501 + map = map->mNext; 25.502 + } 25.503 + if(!map) 25.504 + { 25.505 + self->mError = CTM_INVALID_ARGUMENT; 25.506 + return 0.0f; 25.507 + } 25.508 + 25.509 + // Get the requested string 25.510 + switch(aProperty) 25.511 + { 25.512 + case CTM_PRECISION: 25.513 + return map->mPrecision; 25.514 + 25.515 + default: 25.516 + self->mError = CTM_INVALID_ARGUMENT; 25.517 + } 25.518 + 25.519 + return 0.0f; 25.520 +} 25.521 + 25.522 +//----------------------------------------------------------------------------- 25.523 +// ctmGetAttribMapString() 25.524 +//----------------------------------------------------------------------------- 25.525 +CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext, 25.526 + CTMenum aAttribMap, CTMenum aProperty) 25.527 +{ 25.528 + _CTMcontext * self = (_CTMcontext *) aContext; 25.529 + _CTMfloatmap * map; 25.530 + CTMuint i; 25.531 + if(!self) return (const char *) 0; 25.532 + 25.533 + // Find the indicated map 25.534 + map = self->mAttribMaps; 25.535 + i = CTM_ATTRIB_MAP_1; 25.536 + while(map && (i != aAttribMap)) 25.537 + { 25.538 + ++ i; 25.539 + map = map->mNext; 25.540 + } 25.541 + if(!map) 25.542 + { 25.543 + self->mError = CTM_INVALID_ARGUMENT; 25.544 + return (const char *) 0; 25.545 + } 25.546 + 25.547 + // Get the requested string 25.548 + switch(aProperty) 25.549 + { 25.550 + case CTM_NAME: 25.551 + return (const char *) map->mName; 25.552 + 25.553 + default: 25.554 + self->mError = CTM_INVALID_ARGUMENT; 25.555 + } 25.556 + 25.557 + return (const char *) 0; 25.558 +} 25.559 + 25.560 +//----------------------------------------------------------------------------- 25.561 +// ctmGetAttribMapFloat() 25.562 +//----------------------------------------------------------------------------- 25.563 +CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext, 25.564 + CTMenum aAttribMap, CTMenum aProperty) 25.565 +{ 25.566 + _CTMcontext * self = (_CTMcontext *) aContext; 25.567 + _CTMfloatmap * map; 25.568 + CTMuint i; 25.569 + if(!self) return 0.0f; 25.570 + 25.571 + // Find the indicated map 25.572 + map = self->mAttribMaps; 25.573 + i = CTM_ATTRIB_MAP_1; 25.574 + while(map && (i != aAttribMap)) 25.575 + { 25.576 + ++ i; 25.577 + map = map->mNext; 25.578 + } 25.579 + if(!map) 25.580 + { 25.581 + self->mError = CTM_INVALID_ARGUMENT; 25.582 + return 0.0f; 25.583 + } 25.584 + 25.585 + // Get the requested string 25.586 + switch(aProperty) 25.587 + { 25.588 + case CTM_PRECISION: 25.589 + return map->mPrecision; 25.590 + 25.591 + default: 25.592 + self->mError = CTM_INVALID_ARGUMENT; 25.593 + } 25.594 + 25.595 + return 0.0f; 25.596 +} 25.597 + 25.598 +//----------------------------------------------------------------------------- 25.599 +// ctmGetNamedAttribMap() 25.600 +//----------------------------------------------------------------------------- 25.601 +CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext, 25.602 + const char * aName) 25.603 +{ 25.604 + _CTMcontext * self = (_CTMcontext *) aContext; 25.605 + _CTMfloatmap * map; 25.606 + CTMuint result; 25.607 + if(!self) return CTM_NONE; 25.608 + 25.609 + map = self->mAttribMaps; 25.610 + result = CTM_ATTRIB_MAP_1; 25.611 + while(map && (strcmp(aName, map->mName) != 0)) 25.612 + { 25.613 + map = map->mNext; 25.614 + ++ result; 25.615 + } 25.616 + if(!map) 25.617 + { 25.618 + return CTM_NONE; 25.619 + } 25.620 + return result; 25.621 +} 25.622 + 25.623 +//----------------------------------------------------------------------------- 25.624 +// ctmGetString() 25.625 +//----------------------------------------------------------------------------- 25.626 +CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext, 25.627 + CTMenum aProperty) 25.628 +{ 25.629 + _CTMcontext * self = (_CTMcontext *) aContext; 25.630 + if(!self) return 0; 25.631 + 25.632 + switch(aProperty) 25.633 + { 25.634 + case CTM_FILE_COMMENT: 25.635 + return (const char *) self->mFileComment; 25.636 + 25.637 + default: 25.638 + self->mError = CTM_INVALID_ARGUMENT; 25.639 + } 25.640 + 25.641 + return (const char *) 0; 25.642 +} 25.643 + 25.644 +//----------------------------------------------------------------------------- 25.645 +// ctmCompressionMethod() 25.646 +//----------------------------------------------------------------------------- 25.647 +CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext, 25.648 + CTMenum aMethod) 25.649 +{ 25.650 + _CTMcontext * self = (_CTMcontext *) aContext; 25.651 + if(!self) return; 25.652 + 25.653 + // You are only allowed to change compression attributes in export mode 25.654 + if(self->mMode != CTM_EXPORT) 25.655 + { 25.656 + self->mError = CTM_INVALID_OPERATION; 25.657 + return; 25.658 + } 25.659 + 25.660 + // Check arguments 25.661 + if((aMethod != CTM_METHOD_RAW) && (aMethod != CTM_METHOD_MG1) && 25.662 + (aMethod != CTM_METHOD_MG2)) 25.663 + { 25.664 + self->mError = CTM_INVALID_ARGUMENT; 25.665 + return; 25.666 + } 25.667 + 25.668 + // Set method 25.669 + self->mMethod = aMethod; 25.670 +} 25.671 + 25.672 +//----------------------------------------------------------------------------- 25.673 +// ctmCompressionLevel() 25.674 +//----------------------------------------------------------------------------- 25.675 +CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext, 25.676 + CTMuint aLevel) 25.677 +{ 25.678 + _CTMcontext * self = (_CTMcontext *) aContext; 25.679 + if(!self) return; 25.680 + 25.681 + // You are only allowed to change compression attributes in export mode 25.682 + if(self->mMode != CTM_EXPORT) 25.683 + { 25.684 + self->mError = CTM_INVALID_OPERATION; 25.685 + return; 25.686 + } 25.687 + 25.688 + // Check arguments 25.689 + if(aLevel > 9) 25.690 + { 25.691 + self->mError = CTM_INVALID_ARGUMENT; 25.692 + return; 25.693 + } 25.694 + 25.695 + // Set the compression level 25.696 + self->mCompressionLevel = aLevel; 25.697 +} 25.698 + 25.699 +//----------------------------------------------------------------------------- 25.700 +// ctmVertexPrecision() 25.701 +//----------------------------------------------------------------------------- 25.702 +CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext, 25.703 + CTMfloat aPrecision) 25.704 +{ 25.705 + _CTMcontext * self = (_CTMcontext *) aContext; 25.706 + if(!self) return; 25.707 + 25.708 + // You are only allowed to change compression attributes in export mode 25.709 + if(self->mMode != CTM_EXPORT) 25.710 + { 25.711 + self->mError = CTM_INVALID_OPERATION; 25.712 + return; 25.713 + } 25.714 + 25.715 + // Check arguments 25.716 + if(aPrecision <= 0.0f) 25.717 + { 25.718 + self->mError = CTM_INVALID_ARGUMENT; 25.719 + return; 25.720 + } 25.721 + 25.722 + // Set precision 25.723 + self->mVertexPrecision = aPrecision; 25.724 +} 25.725 + 25.726 +//----------------------------------------------------------------------------- 25.727 +// ctmVertexPrecisionRel() 25.728 +//----------------------------------------------------------------------------- 25.729 +CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext, 25.730 + CTMfloat aRelPrecision) 25.731 +{ 25.732 + _CTMcontext * self = (_CTMcontext *) aContext; 25.733 + CTMfloat avgEdgeLength, * p1, * p2; 25.734 + CTMuint edgeCount, i, j; 25.735 + if(!self) return; 25.736 + 25.737 + // You are only allowed to change compression attributes in export mode 25.738 + if(self->mMode != CTM_EXPORT) 25.739 + { 25.740 + self->mError = CTM_INVALID_OPERATION; 25.741 + return; 25.742 + } 25.743 + 25.744 + // Check arguments 25.745 + if(aRelPrecision <= 0.0f) 25.746 + { 25.747 + self->mError = CTM_INVALID_ARGUMENT; 25.748 + return; 25.749 + } 25.750 + 25.751 + // Calculate the average edge length (Note: we actually sum up all the half- 25.752 + // edges, so in a proper solid mesh all connected edges are counted twice) 25.753 + avgEdgeLength = 0.0f; 25.754 + edgeCount = 0; 25.755 + for(i = 0; i < self->mTriangleCount; ++ i) 25.756 + { 25.757 + p1 = &self->mVertices[self->mIndices[i * 3 + 2] * 3]; 25.758 + for(j = 0; j < 3; ++ j) 25.759 + { 25.760 + p2 = &self->mVertices[self->mIndices[i * 3 + j] * 3]; 25.761 + avgEdgeLength += sqrtf((p2[0] - p1[0]) * (p2[0] - p1[0]) + 25.762 + (p2[1] - p1[1]) * (p2[1] - p1[1]) + 25.763 + (p2[2] - p1[2]) * (p2[2] - p1[2])); 25.764 + p1 = p2; 25.765 + ++ edgeCount; 25.766 + } 25.767 + } 25.768 + if(edgeCount == 0) 25.769 + { 25.770 + self->mError = CTM_INVALID_MESH; 25.771 + return; 25.772 + } 25.773 + avgEdgeLength /= (CTMfloat) edgeCount; 25.774 + 25.775 + // Set precision 25.776 + self->mVertexPrecision = aRelPrecision * avgEdgeLength; 25.777 +} 25.778 + 25.779 +//----------------------------------------------------------------------------- 25.780 +// ctmNormalPrecision() 25.781 +//----------------------------------------------------------------------------- 25.782 +CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext, 25.783 + CTMfloat aPrecision) 25.784 +{ 25.785 + _CTMcontext * self = (_CTMcontext *) aContext; 25.786 + if(!self) return; 25.787 + 25.788 + // You are only allowed to change compression attributes in export mode 25.789 + if(self->mMode != CTM_EXPORT) 25.790 + { 25.791 + self->mError = CTM_INVALID_OPERATION; 25.792 + return; 25.793 + } 25.794 + 25.795 + // Check arguments 25.796 + if(aPrecision <= 0.0f) 25.797 + { 25.798 + self->mError = CTM_INVALID_ARGUMENT; 25.799 + return; 25.800 + } 25.801 + 25.802 + // Set precision 25.803 + self->mNormalPrecision = aPrecision; 25.804 +} 25.805 + 25.806 +//----------------------------------------------------------------------------- 25.807 +// ctmUVCoordPrecision() 25.808 +//----------------------------------------------------------------------------- 25.809 +CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext, 25.810 + CTMenum aUVMap, CTMfloat aPrecision) 25.811 +{ 25.812 + _CTMcontext * self = (_CTMcontext *) aContext; 25.813 + _CTMfloatmap * map; 25.814 + CTMuint i; 25.815 + if(!self) return; 25.816 + 25.817 + // You are only allowed to change compression attributes in export mode 25.818 + if(self->mMode != CTM_EXPORT) 25.819 + { 25.820 + self->mError = CTM_INVALID_OPERATION; 25.821 + return; 25.822 + } 25.823 + 25.824 + // Check arguments 25.825 + if(aPrecision <= 0.0f) 25.826 + { 25.827 + self->mError = CTM_INVALID_ARGUMENT; 25.828 + return; 25.829 + } 25.830 + 25.831 + // Find the indicated map 25.832 + map = self->mUVMaps; 25.833 + i = CTM_UV_MAP_1; 25.834 + while(map && (i != aUVMap)) 25.835 + { 25.836 + ++ i; 25.837 + map = map->mNext; 25.838 + } 25.839 + if(!map) 25.840 + { 25.841 + self->mError = CTM_INVALID_ARGUMENT; 25.842 + return; 25.843 + } 25.844 + 25.845 + // Update the precision 25.846 + map->mPrecision = aPrecision; 25.847 +} 25.848 + 25.849 +//----------------------------------------------------------------------------- 25.850 +// ctmAttribPrecision() 25.851 +//----------------------------------------------------------------------------- 25.852 +CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext, 25.853 + CTMenum aAttribMap, CTMfloat aPrecision) 25.854 +{ 25.855 + _CTMcontext * self = (_CTMcontext *) aContext; 25.856 + _CTMfloatmap * map; 25.857 + CTMuint i; 25.858 + if(!self) return; 25.859 + 25.860 + // You are only allowed to change compression attributes in export mode 25.861 + if(self->mMode != CTM_EXPORT) 25.862 + { 25.863 + self->mError = CTM_INVALID_OPERATION; 25.864 + return; 25.865 + } 25.866 + 25.867 + // Check arguments 25.868 + if(aPrecision <= 0.0f) 25.869 + { 25.870 + self->mError = CTM_INVALID_ARGUMENT; 25.871 + return; 25.872 + } 25.873 + 25.874 + // Find the indicated map 25.875 + map = self->mAttribMaps; 25.876 + i = CTM_ATTRIB_MAP_1; 25.877 + while(map && (i != aAttribMap)) 25.878 + { 25.879 + ++ i; 25.880 + map = map->mNext; 25.881 + } 25.882 + if(!map) 25.883 + { 25.884 + self->mError = CTM_INVALID_ARGUMENT; 25.885 + return; 25.886 + } 25.887 + 25.888 + // Update the precision 25.889 + map->mPrecision = aPrecision; 25.890 +} 25.891 + 25.892 +//----------------------------------------------------------------------------- 25.893 +// ctmFileComment() 25.894 +//----------------------------------------------------------------------------- 25.895 +CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext, 25.896 + const char * aFileComment) 25.897 +{ 25.898 + _CTMcontext * self = (_CTMcontext *) aContext; 25.899 + int len; 25.900 + if(!self) return; 25.901 + 25.902 + // You are only allowed to change file attributes in export mode 25.903 + if(self->mMode != CTM_EXPORT) 25.904 + { 25.905 + self->mError = CTM_INVALID_OPERATION; 25.906 + return; 25.907 + } 25.908 + 25.909 + // Free the old comment string, if necessary 25.910 + if(self->mFileComment) 25.911 + { 25.912 + free(self->mFileComment); 25.913 + self->mFileComment = (char *) 0; 25.914 + } 25.915 + 25.916 + // Get length of string (if empty, do nothing) 25.917 + if(!aFileComment) 25.918 + return; 25.919 + len = strlen(aFileComment); 25.920 + if(!len) 25.921 + return; 25.922 + 25.923 + // Copy the string 25.924 + self->mFileComment = (char *) malloc(len + 1); 25.925 + if(!self->mFileComment) 25.926 + { 25.927 + self->mError = CTM_OUT_OF_MEMORY; 25.928 + return; 25.929 + } 25.930 + strcpy(self->mFileComment, aFileComment); 25.931 +} 25.932 + 25.933 +//----------------------------------------------------------------------------- 25.934 +// ctmDefineMesh() 25.935 +//----------------------------------------------------------------------------- 25.936 +CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext, 25.937 + const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices, 25.938 + CTMuint aTriangleCount, const CTMfloat * aNormals) 25.939 +{ 25.940 + _CTMcontext * self = (_CTMcontext *) aContext; 25.941 + if(!self) return; 25.942 + 25.943 + // You are only allowed to (re)define the mesh in export mode 25.944 + if(self->mMode != CTM_EXPORT) 25.945 + { 25.946 + self->mError = CTM_INVALID_OPERATION; 25.947 + return; 25.948 + } 25.949 + 25.950 + // Check arguments 25.951 + if(!aVertices || !aIndices || !aVertexCount || !aTriangleCount) 25.952 + { 25.953 + self->mError = CTM_INVALID_ARGUMENT; 25.954 + return; 25.955 + } 25.956 + 25.957 + // Clear the old mesh, if any 25.958 + _ctmClearMesh(self); 25.959 + 25.960 + // Set vertex array pointer 25.961 + self->mVertices = (CTMfloat *) aVertices; 25.962 + self->mVertexCount = aVertexCount; 25.963 + 25.964 + // Set index array pointer 25.965 + self->mIndices = (CTMuint *) aIndices; 25.966 + self->mTriangleCount = aTriangleCount; 25.967 + 25.968 + // Set normal array pointer 25.969 + self->mNormals = (CTMfloat *) aNormals; 25.970 +} 25.971 + 25.972 +//----------------------------------------------------------------------------- 25.973 +// _ctmAddFloatMap() 25.974 +//----------------------------------------------------------------------------- 25.975 +static _CTMfloatmap * _ctmAddFloatMap(_CTMcontext * self, 25.976 + const CTMfloat * aValues, const char * aName, const char * aFileName, 25.977 + _CTMfloatmap ** aList) 25.978 +{ 25.979 + _CTMfloatmap * map; 25.980 + CTMuint len; 25.981 + 25.982 + // Allocate memory for a new map list item and append it to the list 25.983 + if(!*aList) 25.984 + { 25.985 + *aList = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); 25.986 + map = *aList; 25.987 + } 25.988 + else 25.989 + { 25.990 + map = *aList; 25.991 + while(map->mNext) 25.992 + map = map->mNext; 25.993 + map->mNext = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); 25.994 + map = map->mNext; 25.995 + } 25.996 + if(!map) 25.997 + { 25.998 + self->mError = CTM_OUT_OF_MEMORY; 25.999 + return (_CTMfloatmap *) 0; 25.1000 + } 25.1001 + 25.1002 + // Init the map item 25.1003 + memset(map, 0, sizeof(_CTMfloatmap)); 25.1004 + map->mPrecision = 1.0f / 1024.0f; 25.1005 + map->mValues = (CTMfloat *) aValues; 25.1006 + 25.1007 + // Set name of the map 25.1008 + if(aName) 25.1009 + { 25.1010 + // Get length of string (if empty, do nothing) 25.1011 + len = strlen(aName); 25.1012 + if(len) 25.1013 + { 25.1014 + // Copy the string 25.1015 + map->mName = (char *) malloc(len + 1); 25.1016 + if(!map->mName) 25.1017 + { 25.1018 + self->mError = CTM_OUT_OF_MEMORY; 25.1019 + free(map); 25.1020 + return (_CTMfloatmap *) 0; 25.1021 + } 25.1022 + strcpy(map->mName, aName); 25.1023 + } 25.1024 + } 25.1025 + 25.1026 + // Set file name reference for the map 25.1027 + if(aFileName) 25.1028 + { 25.1029 + // Get length of string (if empty, do nothing) 25.1030 + len = strlen(aFileName); 25.1031 + if(len) 25.1032 + { 25.1033 + // Copy the string 25.1034 + map->mFileName = (char *) malloc(len + 1); 25.1035 + if(!map->mFileName) 25.1036 + { 25.1037 + self->mError = CTM_OUT_OF_MEMORY; 25.1038 + if(map->mName) 25.1039 + free(map->mName); 25.1040 + free(map); 25.1041 + return (_CTMfloatmap *) 0; 25.1042 + } 25.1043 + strcpy(map->mFileName, aFileName); 25.1044 + } 25.1045 + } 25.1046 + 25.1047 + return map; 25.1048 +} 25.1049 + 25.1050 +//----------------------------------------------------------------------------- 25.1051 +// ctmAddUVMap() 25.1052 +//----------------------------------------------------------------------------- 25.1053 +CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext, 25.1054 + const CTMfloat * aUVCoords, const char * aName, const char * aFileName) 25.1055 +{ 25.1056 + _CTMcontext * self = (_CTMcontext *) aContext; 25.1057 + _CTMfloatmap * map; 25.1058 + if(!self) return CTM_NONE; 25.1059 + 25.1060 + // Add a new UV map to the UV map list 25.1061 + map = _ctmAddFloatMap(self, aUVCoords, aName, aFileName, &self->mUVMaps); 25.1062 + if(!map) 25.1063 + return CTM_NONE; 25.1064 + else 25.1065 + { 25.1066 + // The default UV coordinate precision is 2^-12 25.1067 + map->mPrecision = 1.0f / 4096.0f; 25.1068 + ++ self->mUVMapCount; 25.1069 + return CTM_UV_MAP_1 + self->mUVMapCount - 1; 25.1070 + } 25.1071 +} 25.1072 + 25.1073 +//----------------------------------------------------------------------------- 25.1074 +// ctmAddAttribMap() 25.1075 +//----------------------------------------------------------------------------- 25.1076 +CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext, 25.1077 + const CTMfloat * aAttribValues, const char * aName) 25.1078 +{ 25.1079 + _CTMcontext * self = (_CTMcontext *) aContext; 25.1080 + _CTMfloatmap * map; 25.1081 + if(!self) return CTM_NONE; 25.1082 + 25.1083 + // Add a new attribute map to the attribute map list 25.1084 + map = _ctmAddFloatMap(self, aAttribValues, aName, (const char *) 0, 25.1085 + &self->mAttribMaps); 25.1086 + if(!map) 25.1087 + return CTM_NONE; 25.1088 + else 25.1089 + { 25.1090 + // The default vertex attribute precision is 2^-8 25.1091 + map->mPrecision = 1.0f / 256.0f; 25.1092 + ++ self->mAttribMapCount; 25.1093 + return CTM_ATTRIB_MAP_1 + self->mAttribMapCount - 1; 25.1094 + } 25.1095 +} 25.1096 + 25.1097 +//----------------------------------------------------------------------------- 25.1098 +// _ctmDefaultRead() 25.1099 +//----------------------------------------------------------------------------- 25.1100 +static CTMuint CTMCALL _ctmDefaultRead(void * aBuf, CTMuint aCount, 25.1101 + void * aUserData) 25.1102 +{ 25.1103 + return (CTMuint) fread(aBuf, 1, (size_t) aCount, (FILE *) aUserData); 25.1104 +} 25.1105 + 25.1106 +//----------------------------------------------------------------------------- 25.1107 +// ctmLoad() 25.1108 +//----------------------------------------------------------------------------- 25.1109 +CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName) 25.1110 +{ 25.1111 + _CTMcontext * self = (_CTMcontext *) aContext; 25.1112 + FILE * f; 25.1113 + if(!self) return; 25.1114 + 25.1115 + // You are only allowed to load data in import mode 25.1116 + if(self->mMode != CTM_IMPORT) 25.1117 + { 25.1118 + self->mError = CTM_INVALID_OPERATION; 25.1119 + return; 25.1120 + } 25.1121 + 25.1122 + // Open file stream 25.1123 + f = fopen(aFileName, "rb"); 25.1124 + if(!f) 25.1125 + { 25.1126 + self->mError = CTM_FILE_ERROR; 25.1127 + return; 25.1128 + } 25.1129 + 25.1130 + // Load the file 25.1131 + ctmLoadCustom(self, _ctmDefaultRead, (void *) f); 25.1132 + 25.1133 + // Close file stream 25.1134 + fclose(f); 25.1135 +} 25.1136 + 25.1137 +//----------------------------------------------------------------------------- 25.1138 +// _ctmAllocateFloatMaps() 25.1139 +//----------------------------------------------------------------------------- 25.1140 +static CTMuint _ctmAllocateFloatMaps(_CTMcontext * self, 25.1141 + _CTMfloatmap ** aMapListPtr, CTMuint aCount, CTMuint aChannels) 25.1142 +{ 25.1143 + _CTMfloatmap ** mapListPtr; 25.1144 + CTMuint i, size; 25.1145 + 25.1146 + mapListPtr = aMapListPtr; 25.1147 + for(i = 0; i < aCount; ++ i) 25.1148 + { 25.1149 + // Allocate & clear memory for this map 25.1150 + *mapListPtr = (_CTMfloatmap *) malloc(sizeof(_CTMfloatmap)); 25.1151 + if(!*mapListPtr) 25.1152 + { 25.1153 + self->mError = CTM_OUT_OF_MEMORY; 25.1154 + return CTM_FALSE; 25.1155 + } 25.1156 + memset(*mapListPtr, 0, sizeof(_CTMfloatmap)); 25.1157 + 25.1158 + // Allocate & clear memory for the float array 25.1159 + size = aChannels * sizeof(CTMfloat) * self->mVertexCount; 25.1160 + (*mapListPtr)->mValues = (CTMfloat *) malloc(size); 25.1161 + if(!(*mapListPtr)->mValues) 25.1162 + { 25.1163 + self->mError = CTM_OUT_OF_MEMORY; 25.1164 + return CTM_FALSE; 25.1165 + } 25.1166 + memset((*mapListPtr)->mValues, 0, size); 25.1167 + 25.1168 + // Next map... 25.1169 + mapListPtr = &(*mapListPtr)->mNext; 25.1170 + } 25.1171 + 25.1172 + return CTM_TRUE; 25.1173 +} 25.1174 + 25.1175 +//----------------------------------------------------------------------------- 25.1176 +// ctmLoadCustom() 25.1177 +//----------------------------------------------------------------------------- 25.1178 +CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, 25.1179 + void * aUserData) 25.1180 +{ 25.1181 + _CTMcontext * self = (_CTMcontext *) aContext; 25.1182 + CTMuint formatVersion, flags, method; 25.1183 + if(!self) return; 25.1184 + 25.1185 + // You are only allowed to load data in import mode 25.1186 + if(self->mMode != CTM_IMPORT) 25.1187 + { 25.1188 + self->mError = CTM_INVALID_OPERATION; 25.1189 + return; 25.1190 + } 25.1191 + 25.1192 + // Initialize stream 25.1193 + self->mReadFn = aReadFn; 25.1194 + self->mUserData = aUserData; 25.1195 + 25.1196 + // Clear any old mesh arrays 25.1197 + _ctmClearMesh(self); 25.1198 + 25.1199 + // Read header from stream 25.1200 + if(_ctmStreamReadUINT(self) != FOURCC("OCTM")) 25.1201 + { 25.1202 + self->mError = CTM_BAD_FORMAT; 25.1203 + return; 25.1204 + } 25.1205 + formatVersion = _ctmStreamReadUINT(self); 25.1206 + if(formatVersion != _CTM_FORMAT_VERSION) 25.1207 + { 25.1208 + self->mError = CTM_UNSUPPORTED_FORMAT_VERSION; 25.1209 + return; 25.1210 + } 25.1211 + method = _ctmStreamReadUINT(self); 25.1212 + if(method == FOURCC("RAW\0")) 25.1213 + self->mMethod = CTM_METHOD_RAW; 25.1214 + else if(method == FOURCC("MG1\0")) 25.1215 + self->mMethod = CTM_METHOD_MG1; 25.1216 + else if(method == FOURCC("MG2\0")) 25.1217 + self->mMethod = CTM_METHOD_MG2; 25.1218 + else 25.1219 + { 25.1220 + self->mError = CTM_BAD_FORMAT; 25.1221 + return; 25.1222 + } 25.1223 + self->mVertexCount = _ctmStreamReadUINT(self); 25.1224 + if(self->mVertexCount == 0) 25.1225 + { 25.1226 + self->mError = CTM_BAD_FORMAT; 25.1227 + return; 25.1228 + } 25.1229 + self->mTriangleCount = _ctmStreamReadUINT(self); 25.1230 + if(self->mTriangleCount == 0) 25.1231 + { 25.1232 + self->mError = CTM_BAD_FORMAT; 25.1233 + return; 25.1234 + } 25.1235 + self->mUVMapCount = _ctmStreamReadUINT(self); 25.1236 + self->mAttribMapCount = _ctmStreamReadUINT(self); 25.1237 + flags = _ctmStreamReadUINT(self); 25.1238 + _ctmStreamReadSTRING(self, &self->mFileComment); 25.1239 + 25.1240 + // Allocate memory for the mesh arrays 25.1241 + self->mVertices = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3); 25.1242 + if(!self->mVertices) 25.1243 + { 25.1244 + self->mError = CTM_OUT_OF_MEMORY; 25.1245 + return; 25.1246 + } 25.1247 + self->mIndices = (CTMuint *) malloc(self->mTriangleCount * sizeof(CTMuint) * 3); 25.1248 + if(!self->mIndices) 25.1249 + { 25.1250 + _ctmClearMesh(self); 25.1251 + self->mError = CTM_OUT_OF_MEMORY; 25.1252 + return; 25.1253 + } 25.1254 + if(flags & _CTM_HAS_NORMALS_BIT) 25.1255 + { 25.1256 + self->mNormals = (CTMfloat *) malloc(self->mVertexCount * sizeof(CTMfloat) * 3); 25.1257 + if(!self->mNormals) 25.1258 + { 25.1259 + _ctmClearMesh(self); 25.1260 + self->mError = CTM_OUT_OF_MEMORY; 25.1261 + return; 25.1262 + } 25.1263 + } 25.1264 + 25.1265 + // Allocate memory for the UV and attribute maps (if any) 25.1266 + if(!_ctmAllocateFloatMaps(self, &self->mUVMaps, self->mUVMapCount, 2)) 25.1267 + { 25.1268 + _ctmClearMesh(self); 25.1269 + self->mError = CTM_OUT_OF_MEMORY; 25.1270 + return; 25.1271 + } 25.1272 + if(!_ctmAllocateFloatMaps(self, &self->mAttribMaps, self->mAttribMapCount, 4)) 25.1273 + { 25.1274 + _ctmClearMesh(self); 25.1275 + self->mError = CTM_OUT_OF_MEMORY; 25.1276 + return; 25.1277 + } 25.1278 + 25.1279 + // Uncompress from stream 25.1280 + switch(self->mMethod) 25.1281 + { 25.1282 + case CTM_METHOD_RAW: 25.1283 + _ctmUncompressMesh_RAW(self); 25.1284 + break; 25.1285 + 25.1286 + case CTM_METHOD_MG1: 25.1287 + _ctmUncompressMesh_MG1(self); 25.1288 + break; 25.1289 + 25.1290 + case CTM_METHOD_MG2: 25.1291 + _ctmUncompressMesh_MG2(self); 25.1292 + break; 25.1293 + 25.1294 + default: 25.1295 + self->mError = CTM_INTERNAL_ERROR; 25.1296 + } 25.1297 + 25.1298 + // Check mesh integrity 25.1299 + if(!_ctmCheckMeshIntegrity(self)) 25.1300 + { 25.1301 + self->mError = CTM_INVALID_MESH; 25.1302 + return; 25.1303 + } 25.1304 +} 25.1305 + 25.1306 +//----------------------------------------------------------------------------- 25.1307 +// _ctmDefaultWrite() 25.1308 +//----------------------------------------------------------------------------- 25.1309 +static CTMuint CTMCALL _ctmDefaultWrite(const void * aBuf, CTMuint aCount, 25.1310 + void * aUserData) 25.1311 +{ 25.1312 + return (CTMuint) fwrite(aBuf, 1, (size_t) aCount, (FILE *) aUserData); 25.1313 +} 25.1314 + 25.1315 +//----------------------------------------------------------------------------- 25.1316 +// ctmSave() 25.1317 +//----------------------------------------------------------------------------- 25.1318 +CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName) 25.1319 +{ 25.1320 + _CTMcontext * self = (_CTMcontext *) aContext; 25.1321 + FILE * f; 25.1322 + if(!self) return; 25.1323 + 25.1324 + // You are only allowed to save data in export mode 25.1325 + if(self->mMode != CTM_EXPORT) 25.1326 + { 25.1327 + self->mError = CTM_INVALID_OPERATION; 25.1328 + return; 25.1329 + } 25.1330 + 25.1331 + // Open file stream 25.1332 + f = fopen(aFileName, "wb"); 25.1333 + if(!f) 25.1334 + { 25.1335 + self->mError = CTM_FILE_ERROR; 25.1336 + return; 25.1337 + } 25.1338 + 25.1339 + // Save the file 25.1340 + ctmSaveCustom(self, _ctmDefaultWrite, (void *) f); 25.1341 + 25.1342 + // Close file stream 25.1343 + fclose(f); 25.1344 +} 25.1345 + 25.1346 +//----------------------------------------------------------------------------- 25.1347 +// ctmSaveCustom() 25.1348 +//----------------------------------------------------------------------------- 25.1349 +void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, 25.1350 + void * aUserData) 25.1351 +{ 25.1352 + _CTMcontext * self = (_CTMcontext *) aContext; 25.1353 + CTMuint flags; 25.1354 + if(!self) return; 25.1355 + 25.1356 + // You are only allowed to save data in export mode 25.1357 + if(self->mMode != CTM_EXPORT) 25.1358 + { 25.1359 + self->mError = CTM_INVALID_OPERATION; 25.1360 + return; 25.1361 + } 25.1362 + 25.1363 + // Check mesh integrity 25.1364 + if(!_ctmCheckMeshIntegrity(self)) 25.1365 + { 25.1366 + self->mError = CTM_INVALID_MESH; 25.1367 + return; 25.1368 + } 25.1369 + 25.1370 + // Initialize stream 25.1371 + self->mWriteFn = aWriteFn; 25.1372 + self->mUserData = aUserData; 25.1373 + 25.1374 + // Determine flags 25.1375 + flags = 0; 25.1376 + if(self->mNormals) 25.1377 + flags |= _CTM_HAS_NORMALS_BIT; 25.1378 + 25.1379 + // Write header to stream 25.1380 + _ctmStreamWrite(self, (void *) "OCTM", 4); 25.1381 + _ctmStreamWriteUINT(self, _CTM_FORMAT_VERSION); 25.1382 + switch(self->mMethod) 25.1383 + { 25.1384 + case CTM_METHOD_RAW: 25.1385 + _ctmStreamWrite(self, (void *) "RAW\0", 4); 25.1386 + break; 25.1387 + 25.1388 + case CTM_METHOD_MG1: 25.1389 + _ctmStreamWrite(self, (void *) "MG1\0", 4); 25.1390 + break; 25.1391 + 25.1392 + case CTM_METHOD_MG2: 25.1393 + _ctmStreamWrite(self, (void *) "MG2\0", 4); 25.1394 + break; 25.1395 + 25.1396 + default: 25.1397 + self->mError = CTM_INTERNAL_ERROR; 25.1398 + return; 25.1399 + } 25.1400 + _ctmStreamWriteUINT(self, self->mVertexCount); 25.1401 + _ctmStreamWriteUINT(self, self->mTriangleCount); 25.1402 + _ctmStreamWriteUINT(self, self->mUVMapCount); 25.1403 + _ctmStreamWriteUINT(self, self->mAttribMapCount); 25.1404 + _ctmStreamWriteUINT(self, flags); 25.1405 + _ctmStreamWriteSTRING(self, self->mFileComment); 25.1406 + 25.1407 + // Compress to stream 25.1408 + switch(self->mMethod) 25.1409 + { 25.1410 + case CTM_METHOD_RAW: 25.1411 + _ctmCompressMesh_RAW(self); 25.1412 + break; 25.1413 + 25.1414 + case CTM_METHOD_MG1: 25.1415 + _ctmCompressMesh_MG1(self); 25.1416 + break; 25.1417 + 25.1418 + case CTM_METHOD_MG2: 25.1419 + _ctmCompressMesh_MG2(self); 25.1420 + break; 25.1421 + 25.1422 + default: 25.1423 + self->mError = CTM_INTERNAL_ERROR; 25.1424 + return; 25.1425 + } 25.1426 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/libs/openctm/openctm.h Thu Sep 26 04:47:05 2013 +0300 26.3 @@ -0,0 +1,655 @@ 26.4 +//----------------------------------------------------------------------------- 26.5 +// Product: OpenCTM 26.6 +// File: openctm.h 26.7 +// Description: OpenCTM API definition. 26.8 +//----------------------------------------------------------------------------- 26.9 +// Copyright (c) 2009-2010 Marcus Geelnard 26.10 +// 26.11 +// This software is provided 'as-is', without any express or implied 26.12 +// warranty. In no event will the authors be held liable for any damages 26.13 +// arising from the use of this software. 26.14 +// 26.15 +// Permission is granted to anyone to use this software for any purpose, 26.16 +// including commercial applications, and to alter it and redistribute it 26.17 +// freely, subject to the following restrictions: 26.18 +// 26.19 +// 1. The origin of this software must not be misrepresented; you must not 26.20 +// claim that you wrote the original software. If you use this software 26.21 +// in a product, an acknowledgment in the product documentation would be 26.22 +// appreciated but is not required. 26.23 +// 26.24 +// 2. Altered source versions must be plainly marked as such, and must not 26.25 +// be misrepresented as being the original software. 26.26 +// 26.27 +// 3. This notice may not be removed or altered from any source 26.28 +// distribution. 26.29 +//----------------------------------------------------------------------------- 26.30 + 26.31 +#ifndef __OPENCTM_H_ 26.32 +#define __OPENCTM_H_ 26.33 + 26.34 +/*! @mainpage OpenCTM API Reference 26.35 + * 26.36 + * @section intro_sec Introduction 26.37 + * 26.38 + * OpenCTM is an open file format for storing compressed triangle meshes. 26.39 + * In order to easily read and write OpenCTM files (usually suffixed .ctm) an 26.40 + * API (Application Program Interface) is provided that can easily be used from 26.41 + * most modern programming languages. 26.42 + * 26.43 + * The OpenCTM functionality itself is written in highly portable standard C 26.44 + * (C99). 26.45 + * 26.46 + * @section usage_sec Usage 26.47 + * 26.48 + * For information about how to use the OpenCTM API, see openctm.h. 26.49 + * 26.50 + * For information about the C++ wrapper classes, see CTMimporter and 26.51 + * CTMexporter. 26.52 + * 26.53 + * @section example_sec Example usage 26.54 + * 26.55 + * @subsection example_load_sec Loading a CTM file 26.56 + * 26.57 + * Here is a simple example of loading a CTM file: 26.58 + * 26.59 + * @code 26.60 + * CTMcontext context; 26.61 + * CTMuint vertCount, triCount, * indices; 26.62 + * CTMfloat * vertices; 26.63 + * 26.64 + * // Create a new context 26.65 + * context = ctmNewContext(CTM_IMPORT); 26.66 + * 26.67 + * // Load the OpenCTM file 26.68 + * ctmLoad(context, "mymesh.ctm"); 26.69 + * if(ctmGetError(context) == CTM_NONE) 26.70 + * { 26.71 + * // Access the mesh data 26.72 + * vertCount = ctmGetInteger(context, CTM_VERTEX_COUNT); 26.73 + * vertices = ctmGetFloatArray(context, CTM_VERTICES); 26.74 + * triCount = ctmGetInteger(context, CTM_TRIANGLE_COUNT); 26.75 + * indices = ctmGetIntegerArray(context, CTM_INDICES); 26.76 + * 26.77 + * // Deal with the mesh (e.g. transcode it to our internal representation) 26.78 + * // ... 26.79 + * } 26.80 + * 26.81 + * // Free the context 26.82 + * ctmFreeContext(context); 26.83 + * @endcode 26.84 + * 26.85 + * @subsection example_create_sec Creating a CTM file 26.86 + * 26.87 + * Here is a simple example of creating a CTM file: 26.88 + * 26.89 + * @code 26.90 + * CTMcontext context; 26.91 + * CTMuint vertCount, triCount, * indices; 26.92 + * CTMfloat * vertices; 26.93 + * 26.94 + * // Create our mesh in memory 26.95 + * vertCount = 100; 26.96 + * triCount = 120; 26.97 + * vertices = (CTMfloat *) malloc(3 * sizeof(CTMfloat) * vertCount); 26.98 + * indices = (CTMuint *) malloc(3 * sizeof(CTMuint) * triCount); 26.99 + * // ... 26.100 + * 26.101 + * // Create a new context 26.102 + * context = ctmNewContext(CTM_EXPORT); 26.103 + * 26.104 + * // Define our mesh representation to OpenCTM (store references to it in 26.105 + * // the context) 26.106 + * ctmDefineMesh(context, vertices, vertCount, indices, triCount, NULL); 26.107 + * 26.108 + * // Save the OpenCTM file 26.109 + * ctmSave(context, "mymesh.ctm"); 26.110 + * 26.111 + * // Free the context 26.112 + * ctmFreeContext(context); 26.113 + * 26.114 + * // Free our mesh 26.115 + * free(indices); 26.116 + * free(vertices); 26.117 + * @endcode 26.118 + */ 26.119 + 26.120 +#ifdef __cplusplus 26.121 +extern "C" { 26.122 +#endif 26.123 + 26.124 + 26.125 +// Declare calling conventions etc. 26.126 +#if defined(WIN32) || defined(_WIN32) 26.127 + // Windows 26.128 + #if defined(OPENCTM_STATIC) 26.129 + #define CTMEXPORT 26.130 + #else 26.131 + #if defined(OPENCTM_BUILD) 26.132 + #define CTMEXPORT __declspec(dllexport) 26.133 + #else 26.134 + #define CTMEXPORT __declspec(dllimport) 26.135 + #endif 26.136 + #endif 26.137 + #if defined(__MINGW32__) 26.138 + #define CTMCALL __attribute__ ((__stdcall__)) 26.139 + #elif (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) 26.140 + #define CTMCALL __stdcall 26.141 + #else 26.142 + #define CTMCALL 26.143 + #endif 26.144 +#else 26.145 + // Unix 26.146 + #if !defined(OPENCTM_STATIC) && !defined(OPENCTM_BUILD) 26.147 + #define CTMEXPORT extern 26.148 + #else 26.149 + #if defined(OPENCTM_BUILD) && defined(__GNUC__) && (__GNUC__ >= 4) 26.150 + #define CTMEXPORT __attribute__ ((visibility("default"))) 26.151 + #else 26.152 + #define CTMEXPORT 26.153 + #endif 26.154 + #endif 26.155 + #define CTMCALL 26.156 +#endif 26.157 + 26.158 + 26.159 +// Get system specific type definitions for sized integers. We use the C99 26.160 +// standard stdint.h for this. 26.161 +#ifdef _MSC_VER 26.162 + // MS Visual Studio does not support C99 26.163 + typedef int int32_t; 26.164 + typedef unsigned int uint32_t; 26.165 +#else 26.166 + #include <stdint.h> 26.167 +#endif 26.168 + 26.169 + 26.170 +/// OpenCTM API version (1.0). 26.171 +#define CTM_API_VERSION 0x00000100 26.172 + 26.173 +/// Boolean TRUE. 26.174 +#define CTM_TRUE 1 26.175 + 26.176 +/// Boolean FALSE. 26.177 +#define CTM_FALSE 0 26.178 + 26.179 +/// Single precision floating point type (IEEE 754 32 bits wide). 26.180 +typedef float CTMfloat; 26.181 + 26.182 +/// Signed integer (32 bits wide). 26.183 +typedef int32_t CTMint; 26.184 + 26.185 +/// Unsigned integer (32 bits wide). 26.186 +typedef uint32_t CTMuint; 26.187 + 26.188 +/// OpenCTM context handle. 26.189 +typedef void * CTMcontext; 26.190 + 26.191 +/// OpenCTM specific enumerators. 26.192 +/// @note For the information query functions, it is an error to query a value 26.193 +/// of the wrong type (e.g. to query a string value with the 26.194 +/// ctmGetInteger() function). 26.195 +typedef enum { 26.196 + // Error codes (see ctmGetError()) 26.197 + CTM_NONE = 0x0000, ///< No error has occured (everything is OK). 26.198 + /// Also used as an error return value for 26.199 + /// functions that should return a CTMenum 26.200 + /// value. 26.201 + CTM_INVALID_CONTEXT = 0x0001, ///< The OpenCTM context was invalid (e.g. NULL). 26.202 + CTM_INVALID_ARGUMENT = 0x0002, ///< A function argument was invalid. 26.203 + CTM_INVALID_OPERATION = 0x0003, ///< The operation is not allowed. 26.204 + CTM_INVALID_MESH = 0x0004, ///< The mesh was invalid (e.g. no vertices). 26.205 + CTM_OUT_OF_MEMORY = 0x0005, ///< Not enough memory to proceed. 26.206 + CTM_FILE_ERROR = 0x0006, ///< File I/O error. 26.207 + CTM_BAD_FORMAT = 0x0007, ///< File format error (e.g. unrecognized format or corrupted file). 26.208 + CTM_LZMA_ERROR = 0x0008, ///< An error occured within the LZMA library. 26.209 + CTM_INTERNAL_ERROR = 0x0009, ///< An internal error occured (indicates a bug). 26.210 + CTM_UNSUPPORTED_FORMAT_VERSION = 0x000A, ///< Unsupported file format version. 26.211 + 26.212 + // OpenCTM context modes 26.213 + CTM_IMPORT = 0x0101, ///< The OpenCTM context will be used for importing data. 26.214 + CTM_EXPORT = 0x0102, ///< The OpenCTM context will be used for exporting data. 26.215 + 26.216 + // Compression methods 26.217 + CTM_METHOD_RAW = 0x0201, ///< Just store the raw data. 26.218 + CTM_METHOD_MG1 = 0x0202, ///< Lossless compression (floating point). 26.219 + CTM_METHOD_MG2 = 0x0203, ///< Lossless compression (fixed point). 26.220 + 26.221 + // Context queries 26.222 + CTM_VERTEX_COUNT = 0x0301, ///< Number of vertices in the mesh (integer). 26.223 + CTM_TRIANGLE_COUNT = 0x0302, ///< Number of triangles in the mesh (integer). 26.224 + CTM_HAS_NORMALS = 0x0303, ///< CTM_TRUE if the mesh has normals (integer). 26.225 + CTM_UV_MAP_COUNT = 0x0304, ///< Number of UV coordinate sets (integer). 26.226 + CTM_ATTRIB_MAP_COUNT = 0x0305, ///< Number of custom attribute sets (integer). 26.227 + CTM_VERTEX_PRECISION = 0x0306, ///< Vertex precision - for MG2 (float). 26.228 + CTM_NORMAL_PRECISION = 0x0307, ///< Normal precision - for MG2 (float). 26.229 + CTM_COMPRESSION_METHOD = 0x0308, ///< Compression method (integer). 26.230 + CTM_FILE_COMMENT = 0x0309, ///< File comment (string). 26.231 + 26.232 + // UV/attribute map queries 26.233 + CTM_NAME = 0x0501, ///< Unique name (UV/attrib map string). 26.234 + CTM_FILE_NAME = 0x0502, ///< File name reference (UV map string). 26.235 + CTM_PRECISION = 0x0503, ///< Value precision (UV/attrib map float). 26.236 + 26.237 + // Array queries 26.238 + CTM_INDICES = 0x0601, ///< Triangle indices (integer array). 26.239 + CTM_VERTICES = 0x0602, ///< Vertex point coordinates (float array). 26.240 + CTM_NORMALS = 0x0603, ///< Per vertex normals (float array). 26.241 + CTM_UV_MAP_1 = 0x0700, ///< Per vertex UV map 1 (float array). 26.242 + CTM_UV_MAP_2 = 0x0701, ///< Per vertex UV map 2 (float array). 26.243 + CTM_UV_MAP_3 = 0x0702, ///< Per vertex UV map 3 (float array). 26.244 + CTM_UV_MAP_4 = 0x0703, ///< Per vertex UV map 4 (float array). 26.245 + CTM_UV_MAP_5 = 0x0704, ///< Per vertex UV map 5 (float array). 26.246 + CTM_UV_MAP_6 = 0x0705, ///< Per vertex UV map 6 (float array). 26.247 + CTM_UV_MAP_7 = 0x0706, ///< Per vertex UV map 7 (float array). 26.248 + CTM_UV_MAP_8 = 0x0707, ///< Per vertex UV map 8 (float array). 26.249 + CTM_ATTRIB_MAP_1 = 0x0800, ///< Per vertex attribute map 1 (float array). 26.250 + CTM_ATTRIB_MAP_2 = 0x0801, ///< Per vertex attribute map 2 (float array). 26.251 + CTM_ATTRIB_MAP_3 = 0x0802, ///< Per vertex attribute map 3 (float array). 26.252 + CTM_ATTRIB_MAP_4 = 0x0803, ///< Per vertex attribute map 4 (float array). 26.253 + CTM_ATTRIB_MAP_5 = 0x0804, ///< Per vertex attribute map 5 (float array). 26.254 + CTM_ATTRIB_MAP_6 = 0x0805, ///< Per vertex attribute map 6 (float array). 26.255 + CTM_ATTRIB_MAP_7 = 0x0806, ///< Per vertex attribute map 7 (float array). 26.256 + CTM_ATTRIB_MAP_8 = 0x0807 ///< Per vertex attribute map 8 (float array). 26.257 +} CTMenum; 26.258 + 26.259 +/// Stream read() function pointer. 26.260 +/// @param[in] aBuf Pointer to the memory buffer to which data should be read. 26.261 +/// @param[in] aCount The number of bytes to read. 26.262 +/// @param[in] aUserData The custom user data that was passed to the 26.263 +/// ctmLoadCustom() function. 26.264 +/// @return The number of bytes actually read (if this is less than aCount, it 26.265 +/// indicates that an error occured or the end of file was reached 26.266 +/// before all bytes were read). 26.267 +typedef CTMuint (CTMCALL * CTMreadfn)(void * aBuf, CTMuint aCount, void * aUserData); 26.268 + 26.269 +/// Stream write() function pointer. 26.270 +/// @param[in] aBuf Pointer to the memory buffer from which data should be written. 26.271 +/// @param[in] aCount The number of bytes to write. 26.272 +/// @param[in] aUserData The custom user data that was passed to the 26.273 +/// ctmSaveCustom() function. 26.274 +/// @return The number of bytes actually written (if this is less than aCount, it 26.275 +/// indicates that an error occured). 26.276 +typedef CTMuint (CTMCALL * CTMwritefn)(const void * aBuf, CTMuint aCount, void * aUserData); 26.277 + 26.278 +/// Create a new OpenCTM context. The context is used for all subsequent 26.279 +/// OpenCTM function calls. Several contexts can coexist at the same time. 26.280 +/// @param[in] aMode An OpenCTM context mode. Set this to CTM_IMPORT if the 26.281 +/// context will be used for importing data, or set it to CTM_EXPORT 26.282 +/// if it will be used for exporting data. 26.283 +/// @return An OpenCTM context handle (or NULL if no context could be created). 26.284 +CTMEXPORT CTMcontext CTMCALL ctmNewContext(CTMenum aMode); 26.285 + 26.286 +/// Free an OpenCTM context. 26.287 +/// @param[in] aContext An OpenCTM context that has been created by 26.288 +/// ctmNewContext(). 26.289 +/// @see ctmNewContext() 26.290 +CTMEXPORT void CTMCALL ctmFreeContext(CTMcontext aContext); 26.291 + 26.292 +/// Returns the latest error. Calling this function will return the last 26.293 +/// produced error code, or CTM_NO_ERROR (zero) if no error has occured since 26.294 +/// the last call to ctmGetError(). When this function is called, the internal 26.295 +/// error varibale will be reset to CTM_NONE. 26.296 +/// @param[in] aContext An OpenCTM context that has been created by 26.297 +/// ctmNewContext(). 26.298 +/// @return An OpenCTM error code. 26.299 +/// @see CTMenum 26.300 +CTMEXPORT CTMenum CTMCALL ctmGetError(CTMcontext aContext); 26.301 + 26.302 +/// Converts an OpenCTM error code to a zero-terminated string. 26.303 +/// @param[in] aError An OpenCTM error code, as returned by ctmGetError(). 26.304 +/// @return A zero terminated string that describes the error. For instance, 26.305 +/// if \c aError is CTM_INVALID_OPERATION, then the return value will 26.306 +/// be "CTM_INVALID_OPERATION". 26.307 +/// @see CTMenum 26.308 +CTMEXPORT const char * CTMCALL ctmErrorString(CTMenum aError); 26.309 + 26.310 +/// Get information about an OpenCTM context. 26.311 +/// @param[in] aContext An OpenCTM context that has been created by 26.312 +/// ctmNewContext(). 26.313 +/// @param[in] aProperty Which property to return. 26.314 +/// @return An integer value, representing the OpenCTM context property given 26.315 +/// by \c aProperty. 26.316 +/// @see CTMenum 26.317 +CTMEXPORT CTMuint CTMCALL ctmGetInteger(CTMcontext aContext, CTMenum aProperty); 26.318 + 26.319 +/// Get information about an OpenCTM context. 26.320 +/// @param[in] aContext An OpenCTM context that has been created by 26.321 +/// ctmNewContext(). 26.322 +/// @param[in] aProperty Which property to return. 26.323 +/// @return A floating point value, representing the OpenCTM context property 26.324 +/// given by \c aProperty. 26.325 +/// @see CTMenum 26.326 +CTMEXPORT CTMfloat CTMCALL ctmGetFloat(CTMcontext aContext, CTMenum aProperty); 26.327 + 26.328 +/// Get an integer array from an OpenCTM context. 26.329 +/// @param[in] aContext An OpenCTM context that has been created by 26.330 +/// ctmNewContext(). 26.331 +/// @param[in] aProperty Which array to return. 26.332 +/// @return An integer array. If the requested array does not exist, or 26.333 +/// if \c aProperty does not indicate an integer array, the function 26.334 +/// returns NULL. 26.335 +/// @note The array is only valid as long as the OpenCTM context is valid, or 26.336 +/// until the corresponding array changes within the OpenCTM context. 26.337 +/// Trying to access an invalid array will result in undefined 26.338 +/// behaviour. Therefor it is recommended that the array is copied to 26.339 +/// a new variable if it is to be used other than directly after the call 26.340 +/// to ctmGetIntegerArray(). 26.341 +/// @see CTMenum 26.342 +CTMEXPORT const CTMuint * CTMCALL ctmGetIntegerArray(CTMcontext aContext, 26.343 + CTMenum aProperty); 26.344 + 26.345 +/// Get a floating point array from an OpenCTM context. 26.346 +/// @param[in] aContext An OpenCTM context that has been created by 26.347 +/// ctmNewContext(). 26.348 +/// @param[in] aProperty Which array to return. 26.349 +/// @return A floating point array. If the requested array does not exist, or 26.350 +/// if \c aProperty does not indicate a float array, the function 26.351 +/// returns NULL. 26.352 +/// @note The array is only valid as long as the OpenCTM context is valid, or 26.353 +/// until the corresponding array changes within the OpenCTM context. 26.354 +/// Trying to access an invalid array will result in undefined 26.355 +/// behaviour. Therefor it is recommended that the array is copied to 26.356 +/// a new variable if it is to be used other than directly after the call 26.357 +/// to ctmGetFloatArray(). 26.358 +/// @see CTMenum 26.359 +CTMEXPORT const CTMfloat * CTMCALL ctmGetFloatArray(CTMcontext aContext, 26.360 + CTMenum aProperty); 26.361 + 26.362 +/// Get a reference to the named UV map. 26.363 +/// @param[in] aContext An OpenCTM context that has been created by 26.364 +/// ctmNewContext(). 26.365 +/// @param[in] aName The name of the UV map that should be returned. 26.366 +/// @return A reference to a UV map. If the UV map was found, a value of 26.367 +/// CTM_UV_MAP_1 or higher is returned, otherwise CTM_NONE is 26.368 +/// returned. 26.369 +CTMEXPORT CTMenum CTMCALL ctmGetNamedUVMap(CTMcontext aContext, 26.370 + const char * aName); 26.371 + 26.372 +/// Get information about a UV map. 26.373 +/// @param[in] aContext An OpenCTM context that has been created by 26.374 +/// ctmNewContext(). 26.375 +/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher). 26.376 +/// @param[in] aProperty Which UV map property to return. 26.377 +/// @return A string value, representing the UV map property given 26.378 +/// by \c aProperty. 26.379 +/// @note The string is only valid as long as the UV map within the OpenCTM 26.380 +/// context is valid. Trying to access an invalid string will result in 26.381 +/// undefined behaviour. Therefor it is recommended that the string is 26.382 +/// copied to a new variable if it is to be used other than directly after 26.383 +/// the call to ctmGetUVMapString(). 26.384 +/// @see CTMenum 26.385 +CTMEXPORT const char * CTMCALL ctmGetUVMapString(CTMcontext aContext, 26.386 + CTMenum aUVMap, CTMenum aProperty); 26.387 + 26.388 +/// Get information about a UV map. 26.389 +/// @param[in] aContext An OpenCTM context that has been created by 26.390 +/// ctmNewContext(). 26.391 +/// @param[in] aUVMap Which UV map to query (CTM_UV_MAP_1 or higher). 26.392 +/// @param[in] aProperty Which UV map property to return. 26.393 +/// @return A floating point value, representing the UV map property given 26.394 +/// by \c aProperty. 26.395 +/// @see CTMenum 26.396 +CTMEXPORT CTMfloat CTMCALL ctmGetUVMapFloat(CTMcontext aContext, 26.397 + CTMenum aUVMap, CTMenum aProperty); 26.398 + 26.399 +/// Get a reference to the named vertex attribute map. 26.400 +/// @param[in] aContext An OpenCTM context that has been created by 26.401 +/// ctmNewContext(). 26.402 +/// @param[in] aName The name of the attribute map that should be returned. 26.403 +/// @return A reference to an attribute map. If the attribute map was found, 26.404 +/// a value of CTM_ATTRIB_MAP_1 or higher is returned, otherwise 26.405 +/// CTM_NONE is returned. 26.406 +CTMEXPORT CTMenum CTMCALL ctmGetNamedAttribMap(CTMcontext aContext, 26.407 + const char * aName); 26.408 + 26.409 +/// Get information about a vertex attribute map. 26.410 +/// @param[in] aContext An OpenCTM context that has been created by 26.411 +/// ctmNewContext(). 26.412 +/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 26.413 +/// or higher). 26.414 +/// @param[in] aProperty Which vertex attribute map property to return. 26.415 +/// @return A string value, representing the vertex attribute map property given 26.416 +/// by \c aProperty. 26.417 +/// @note The string is only valid as long as the vertex attribute map within 26.418 +/// the OpenCTM context is valid. Trying to access an invalid string will 26.419 +/// result in undefined behaviour. Therefor it is recommended that the 26.420 +/// string is copied to a new variable if it is to be used other than 26.421 +/// directly after the call to ctmGetAttribMapString(). 26.422 +/// @see CTMenum 26.423 +CTMEXPORT const char * CTMCALL ctmGetAttribMapString(CTMcontext aContext, 26.424 + CTMenum aAttribMap, CTMenum aProperty); 26.425 + 26.426 +/// Get information about a vertex attribute map. 26.427 +/// @param[in] aContext An OpenCTM context that has been created by 26.428 +/// ctmNewContext(). 26.429 +/// @param[in] aAttribMap Which vertex attribute map to query (CTM_ATTRIB_MAP_1 26.430 +/// or higher). 26.431 +/// @param[in] aProperty Which vertex attribute map property to return. 26.432 +/// @return A floating point value, representing the vertex attribute map 26.433 +/// property given by \c aProperty. 26.434 +/// @see CTMenum 26.435 +CTMEXPORT CTMfloat CTMCALL ctmGetAttribMapFloat(CTMcontext aContext, 26.436 + CTMenum aAttribMap, CTMenum aProperty); 26.437 + 26.438 +/// Get information about an OpenCTM context. 26.439 +/// @param[in] aContext An OpenCTM context that has been created by 26.440 +/// ctmNewContext(). 26.441 +/// @param[in] aProperty Which property to return. 26.442 +/// @return A string value, representing the OpenCTM context property given 26.443 +/// by \c aProperty. 26.444 +/// @note The string is only valid as long as the OpenCTM context is valid, or 26.445 +/// until the corresponding string changes within the OpenCTM context 26.446 +/// (e.g. calling ctmFileComment() invalidates the CTM_FILE_COMMENT 26.447 +/// string). Trying to access an invalid string will result in undefined 26.448 +/// behaviour. Therefor it is recommended that the string is copied to 26.449 +/// a new variable if it is to be used other than directly after the call 26.450 +/// to ctmGetString(). 26.451 +/// @see CTMenum 26.452 +CTMEXPORT const char * CTMCALL ctmGetString(CTMcontext aContext, 26.453 + CTMenum aProperty); 26.454 + 26.455 +/// Set which compression method to use for the given OpenCTM context. 26.456 +/// The selected compression method will be used when calling the ctmSave() 26.457 +/// function. 26.458 +/// @param[in] aContext An OpenCTM context that has been created by 26.459 +/// ctmNewContext(). 26.460 +/// @param[in] aMethod Which compression method to use: CTM_METHOD_RAW, 26.461 +/// CTM_METHOD_MG1 or CTM_METHOD_MG2 (the default method is 26.462 +/// CTM_METHOD_MG1). 26.463 +/// @see CTM_METHOD_RAW, CTM_METHOD_MG1, CTM_METHOD_MG2 26.464 +CTMEXPORT void CTMCALL ctmCompressionMethod(CTMcontext aContext, 26.465 + CTMenum aMethod); 26.466 + 26.467 +/// Set which LZMA compression level to use for the given OpenCTM context. 26.468 +/// The compression level can be between 0 (fastest) and 9 (best). The higher 26.469 +/// the compression level, the more memory is required for compression and 26.470 +/// decompression. The default compression level is 1. 26.471 +/// @param[in] aContext An OpenCTM context that has been created by 26.472 +/// ctmNewContext(). 26.473 +/// @param[in] aLevel Which compression level to use (0 to 9). 26.474 +CTMEXPORT void CTMCALL ctmCompressionLevel(CTMcontext aContext, 26.475 + CTMuint aLevel); 26.476 + 26.477 +/// Set the vertex coordinate precision (only used by the MG2 compression 26.478 +/// method). 26.479 +/// @param[in] aContext An OpenCTM context that has been created by 26.480 +/// ctmNewContext(). 26.481 +/// @param[in] aPrecision Fixed point precision. For instance, if this value is 26.482 +/// 0.001, all vertex coordinates will be rounded to three decimals. 26.483 +/// The default vertex coordinate precision is 2^-10 ~= 0.00098. 26.484 +CTMEXPORT void CTMCALL ctmVertexPrecision(CTMcontext aContext, 26.485 + CTMfloat aPrecision); 26.486 + 26.487 +/// Set the vertex coordinate precision, relative to the mesh dimensions (only 26.488 +/// used by the MG2 compression method). 26.489 +/// @param[in] aContext An OpenCTM context that has been created by 26.490 +/// ctmNewContext(). 26.491 +/// @param[in] aRelPrecision Relative precision. This factor is multiplied by the 26.492 +/// average triangle edge length in the mesh in order to obtain the 26.493 +/// final, fixed point precision. For instance, if aRelPrecision is 26.494 +/// 0.01, and the average edge length is 3.7, then the fixed point 26.495 +/// precision is set to 0.037. 26.496 +/// @note The mesh must have been defined using the ctmDefineMesh() function 26.497 +/// before calling this function. 26.498 +/// @see ctmVertexPrecision(). 26.499 +CTMEXPORT void CTMCALL ctmVertexPrecisionRel(CTMcontext aContext, 26.500 + CTMfloat aRelPrecision); 26.501 + 26.502 +/// Set the normal precision (only used by the MG2 compression method). The 26.503 +/// normal is represented in spherical coordinates in the MG2 compression 26.504 +/// method, and the normal precision controls the angular and radial resolution. 26.505 +/// @param[in] aContext An OpenCTM context that has been created by 26.506 +/// ctmNewContext(). 26.507 +/// @param[in] aPrecision Fixed point precision. For the angular information, 26.508 +/// this value represents the angular precision. For the radial 26.509 +/// information, this value is the linear resolution. For instance, 26.510 +/// 0.01 means that the circle is divided into 100 steps, and the 26.511 +/// normal magnitude is rounded to 2 decimals. The default normal 26.512 +/// precision is 2^-8 ~= 0.0039. 26.513 +CTMEXPORT void CTMCALL ctmNormalPrecision(CTMcontext aContext, 26.514 + CTMfloat aPrecision); 26.515 + 26.516 +/// Set the coordinate precision for the specified UV map (only used by the 26.517 +/// MG2 compression method). 26.518 +/// @param[in] aContext An OpenCTM context that has been created by 26.519 +/// ctmNewContext(). 26.520 +/// @param[in] aUVMap A UV map specifier for a defined UV map 26.521 +/// (CTM_UV_MAP_1, ...). 26.522 +/// @param[in] aPrecision Fixed point precision. For instance, if this value is 26.523 +/// 0.001, all UV coordinates will be rounded to three decimals. 26.524 +/// The default UV coordinate precision is 2^-12 ~= 0.00024. 26.525 +/// @see ctmAddUVMap(). 26.526 +CTMEXPORT void CTMCALL ctmUVCoordPrecision(CTMcontext aContext, 26.527 + CTMenum aUVMap, CTMfloat aPrecision); 26.528 + 26.529 +/// Set the attribute value precision for the specified attribute map (only 26.530 +/// used by the MG2 compression method). 26.531 +/// @param[in] aContext An OpenCTM context that has been created by 26.532 +/// ctmNewContext(). 26.533 +/// @param[in] aAttribMap An attribute map specifier for a defined attribute map 26.534 +/// (CTM_ATTRIB_MAP_1, ...). 26.535 +/// @param[in] aPrecision Fixed point precision. For instance, if this value is 26.536 +/// 0.001, all attribute values will be rounded to three decimals. 26.537 +/// If the attributes represent integer values, set the precision 26.538 +/// to 1.0. The default attribute precision is 2^-8 ~= 0.0039. 26.539 +/// @see ctmAddAttribMap(). 26.540 +CTMEXPORT void CTMCALL ctmAttribPrecision(CTMcontext aContext, 26.541 + CTMenum aAttribMap, CTMfloat aPrecision); 26.542 + 26.543 +/// Set the file comment for the given OpenCTM context. 26.544 +/// @param[in] aContext An OpenCTM context that has been created by 26.545 +/// ctmNewContext(). 26.546 +/// @param[in] aFileComment The file comment (zero terminated UTF-8 string). 26.547 +CTMEXPORT void CTMCALL ctmFileComment(CTMcontext aContext, 26.548 + const char * aFileComment); 26.549 + 26.550 +/// Define a triangle mesh. 26.551 +/// @param[in] aContext An OpenCTM context that has been created by 26.552 +/// ctmNewContext(). 26.553 +/// @param[in] aVertices An array of vertices (three consecutive floats make 26.554 +/// one vertex). 26.555 +/// @param[in] aVertexCount The number of vertices in \c aVertices (and 26.556 +/// optionally \c aTexCoords). 26.557 +/// @param[in] aIndices An array of vertex indices (three consecutive integers 26.558 +/// make one triangle). 26.559 +/// @param[in] aTriangleCount The number of triangles in \c aIndices (there 26.560 +/// must be exactly 3 x \c aTriangleCount indices in \c aIndices). 26.561 +/// @param[in] aNormals An array of per-vertex normals (or NULL if there are 26.562 +/// no normals). Each normal is made up by three consecutive floats, 26.563 +/// and there must be \c aVertexCount normals. 26.564 +/// @see ctmAddUVMap(), ctmAddAttribMap(), ctmSave(), ctmSaveCustom(). 26.565 +CTMEXPORT void CTMCALL ctmDefineMesh(CTMcontext aContext, 26.566 + const CTMfloat * aVertices, CTMuint aVertexCount, const CTMuint * aIndices, 26.567 + CTMuint aTriangleCount, const CTMfloat * aNormals); 26.568 + 26.569 +/// Define a UV map. There can be several UV maps in a mesh. A UV map is 26.570 +/// typically used for 2D texture mapping. 26.571 +/// @param[in] aContext An OpenCTM context that has been created by 26.572 +/// ctmNewContext(). 26.573 +/// @param[in] aUVCoords An array of UV coordinates. Each UV coordinate is made 26.574 +/// up by two consecutive floats, and there must be as many 26.575 +/// coordinates as there are vertices in the mesh. 26.576 +/// @param[in] aName A unique name for this UV map (zero terminated UTF-8 26.577 +/// string). 26.578 +/// @param[in] aFileName A reference to a image file (zero terminated 26.579 +/// UTF-8 string). If no file name reference exists, pass NULL. 26.580 +/// @return A UV map index (CTM_UV_MAP_1 and higher). If the function 26.581 +/// failed, it will return the zero valued CTM_NONE (use ctmGetError() 26.582 +/// to determine the cause of the error). 26.583 +/// @note A triangle mesh must have been defined before calling this function, 26.584 +/// since the number of vertices is defined by the triangle mesh. 26.585 +/// @see ctmDefineMesh(). 26.586 +CTMEXPORT CTMenum CTMCALL ctmAddUVMap(CTMcontext aContext, 26.587 + const CTMfloat * aUVCoords, const char * aName, const char * aFileName); 26.588 + 26.589 +/// Define a custom vertex attribute map. Custom vertex attributes can be used 26.590 +/// for defining special per-vertex attributes, such as color, weight, ambient 26.591 +/// occlusion factor, etc. 26.592 +/// @param[in] aContext An OpenCTM context that has been created by 26.593 +/// ctmNewContext(). 26.594 +/// @param[in] aAttribValues An array of attribute values. Each attribute value 26.595 +/// is made up by four consecutive floats, and there must be as many 26.596 +/// values as there are vertices in the mesh. 26.597 +/// @param[in] aName A unique name for this attribute map (zero terminated UTF-8 26.598 +/// string). 26.599 +/// @return A attribute map index (CTM_ATTRIB_MAP_1 and higher). If the function 26.600 +/// failed, it will return the zero valued CTM_NONE (use ctmGetError() 26.601 +/// to determine the cause of the error). 26.602 +/// @note A triangle mesh must have been defined before calling this function, 26.603 +/// since the number of vertices is defined by the triangle mesh. 26.604 +/// @see ctmDefineMesh(). 26.605 +CTMEXPORT CTMenum CTMCALL ctmAddAttribMap(CTMcontext aContext, 26.606 + const CTMfloat * aAttribValues, const char * aName); 26.607 + 26.608 +/// Load an OpenCTM format file into the context. The mesh data can be retrieved 26.609 +/// with the various ctmGet functions. 26.610 +/// @param[in] aContext An OpenCTM context that has been created by 26.611 +/// ctmNewContext(). 26.612 +/// @param[in] aFileName The name of the file to be loaded. 26.613 +CTMEXPORT void CTMCALL ctmLoad(CTMcontext aContext, const char * aFileName); 26.614 + 26.615 +/// Load an OpenCTM format file using a custom stream read function. The mesh 26.616 +/// data can be retrieved with the various ctmGet functions. 26.617 +/// @param[in] aContext An OpenCTM context that has been created by 26.618 +/// ctmNewContext(). 26.619 +/// @param[in] aReadFn Pointer to a custom stream read function. 26.620 +/// @param[in] aUserData Custom user data, which can be a C language FILE 26.621 +/// handle, C++ istream object, or a custom object pointer 26.622 +/// of any type. The user data pointer will be passed to the 26.623 +/// custom stream read function. 26.624 +/// @see CTMreadfn. 26.625 +CTMEXPORT void CTMCALL ctmLoadCustom(CTMcontext aContext, CTMreadfn aReadFn, 26.626 + void * aUserData); 26.627 + 26.628 +/// Save an OpenCTM format file. The mesh must have been defined by 26.629 +/// ctmDefineMesh(). 26.630 +/// @param[in] aContext An OpenCTM context that has been created by 26.631 +/// ctmNewContext(). 26.632 +/// @param[in] aFileName The name of the file to be saved. 26.633 +CTMEXPORT void CTMCALL ctmSave(CTMcontext aContext, const char * aFileName); 26.634 + 26.635 +/// Save an OpenCTM format file using a custom stream write function. The mesh 26.636 +/// must have been defined by ctmDefineMesh(). 26.637 +/// @param[in] aContext An OpenCTM context that has been created by 26.638 +/// ctmNewContext(). 26.639 +/// @param[in] aWriteFn Pointer to a custom stream write function. 26.640 +/// @param[in] aUserData Custom user data, which can be a C language FILE 26.641 +/// handle, C++ ostream object, or a custom object pointer 26.642 +/// of any type. The user data pointer will be passed to the 26.643 +/// custom stream write function. 26.644 +/// @see CTMwritefn. 26.645 +CTMEXPORT void CTMCALL ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, 26.646 + void * aUserData); 26.647 + 26.648 +#ifdef __cplusplus 26.649 +} 26.650 +#endif 26.651 + 26.652 + 26.653 +// C++ extensions to the API (to disable C++ extensions, define OPENCTM_NO_CPP) 26.654 +#if defined(__cplusplus) && !defined(OPENCTM_NO_CPP) 26.655 + #include "openctmpp.h" 26.656 +#endif 26.657 + 26.658 +#endif // __OPENCTM_H_
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/libs/openctm/openctmpp.h Thu Sep 26 04:47:05 2013 +0300 27.3 @@ -0,0 +1,377 @@ 27.4 +//----------------------------------------------------------------------------- 27.5 +// Product: OpenCTM 27.6 +// File: openctmpp.h 27.7 +// Description: C++ wrapper for the OpenCTM API. 27.8 +//----------------------------------------------------------------------------- 27.9 +// Copyright (c) 2009-2010 Marcus Geelnard 27.10 +// 27.11 +// This software is provided 'as-is', without any express or implied 27.12 +// warranty. In no event will the authors be held liable for any damages 27.13 +// arising from the use of this software. 27.14 +// 27.15 +// Permission is granted to anyone to use this software for any purpose, 27.16 +// including commercial applications, and to alter it and redistribute it 27.17 +// freely, subject to the following restrictions: 27.18 +// 27.19 +// 1. The origin of this software must not be misrepresented; you must not 27.20 +// claim that you wrote the original software. If you use this software 27.21 +// in a product, an acknowledgment in the product documentation would be 27.22 +// appreciated but is not required. 27.23 +// 27.24 +// 2. Altered source versions must be plainly marked as such, and must not 27.25 +// be misrepresented as being the original software. 27.26 +// 27.27 +// 3. This notice may not be removed or altered from any source 27.28 +// distribution. 27.29 +//----------------------------------------------------------------------------- 27.30 + 27.31 +// To disable C++ extensions, define OPENCTM_NO_CPP 27.32 +#ifndef OPENCTM_NO_CPP 27.33 + 27.34 +#ifndef __OPENCTMPP_H_ 27.35 +#define __OPENCTMPP_H_ 27.36 + 27.37 +// Just in case (if this file was included from outside openctm.h)... 27.38 +#ifndef __OPENCTM_H_ 27.39 +#include "openctm.h" 27.40 +#endif 27.41 + 27.42 +#include <exception> 27.43 + 27.44 +/// OpenCTM exception. When an error occurs, a \c ctm_error exception is 27.45 +/// thrown. Its what() function returns the name of the OpenCTM error code 27.46 +/// (for instance "CTM_INVALID_OPERATION"). 27.47 +class ctm_error: public std::exception 27.48 +{ 27.49 + private: 27.50 + CTMenum mErrorCode; 27.51 + 27.52 + public: 27.53 + explicit ctm_error(CTMenum aError) 27.54 + { 27.55 + mErrorCode = aError; 27.56 + } 27.57 + 27.58 + virtual const char* what() const throw() 27.59 + { 27.60 + return ctmErrorString(mErrorCode); 27.61 + } 27.62 + 27.63 + CTMenum error_code() const throw() 27.64 + { 27.65 + return mErrorCode; 27.66 + } 27.67 +}; 27.68 + 27.69 + 27.70 +/// OpenCTM importer class. This is a C++ wrapper class for an OpenCTM import 27.71 +/// context. Usage example: 27.72 +/// 27.73 +/// @code 27.74 +/// // Create a new OpenCTM importer object 27.75 +/// CTMimporter ctm; 27.76 +/// 27.77 +/// // Load the OpenCTM file 27.78 +/// ctm.Load("mymesh.ctm"); 27.79 +/// 27.80 +/// // Access the mesh data 27.81 +/// vertCount = ctm.GetInteger(CTM_VERTEX_COUNT); 27.82 +/// vertices = ctm.GetFloatArray(CTM_VERTICES); 27.83 +/// triCount = ctm.GetInteger(CTM_TRIANGLE_COUNT); 27.84 +/// indices = ctm.GetIntegerArray(CTM_INDICES); 27.85 +/// 27.86 +/// // Deal with the mesh (e.g. transcode it to our internal representation) 27.87 +/// // ... 27.88 +/// @endcode 27.89 + 27.90 +class CTMimporter { 27.91 + private: 27.92 + /// The OpenCTM context handle. 27.93 + CTMcontext mContext; 27.94 + 27.95 + /// Check for OpenCTM errors, and throw an exception if an error has 27.96 + /// occured. 27.97 + void CheckError() 27.98 + { 27.99 + CTMenum err = ctmGetError(mContext); 27.100 + if(err != CTM_NONE) 27.101 + throw ctm_error(err); 27.102 + } 27.103 + 27.104 + public: 27.105 + /// Constructor 27.106 + CTMimporter() 27.107 + { 27.108 + mContext = ctmNewContext(CTM_IMPORT); 27.109 + } 27.110 + 27.111 + /// Destructor 27.112 + ~CTMimporter() 27.113 + { 27.114 + ctmFreeContext(mContext); 27.115 + } 27.116 + 27.117 + /// Wrapper for ctmGetInteger() 27.118 + CTMuint GetInteger(CTMenum aProperty) 27.119 + { 27.120 + CTMuint res = ctmGetInteger(mContext, aProperty); 27.121 + CheckError(); 27.122 + return res; 27.123 + } 27.124 + 27.125 + /// Wrapper for ctmGetFloat() 27.126 + CTMfloat GetFloat(CTMenum aProperty) 27.127 + { 27.128 + CTMfloat res = ctmGetFloat(mContext, aProperty); 27.129 + CheckError(); 27.130 + return res; 27.131 + } 27.132 + 27.133 + /// Wrapper for ctmGetIntegerArray() 27.134 + const CTMuint * GetIntegerArray(CTMenum aProperty) 27.135 + { 27.136 + const CTMuint * res = ctmGetIntegerArray(mContext, aProperty); 27.137 + CheckError(); 27.138 + return res; 27.139 + } 27.140 + 27.141 + /// Wrapper for ctmGetFloatArray() 27.142 + const CTMfloat * GetFloatArray(CTMenum aProperty) 27.143 + { 27.144 + const CTMfloat * res = ctmGetFloatArray(mContext, aProperty); 27.145 + CheckError(); 27.146 + return res; 27.147 + } 27.148 + 27.149 + /// Wrapper for ctmGetNamedUVMap() 27.150 + CTMenum GetNamedUVMap(const char * aName) 27.151 + { 27.152 + CTMenum res = ctmGetNamedUVMap(mContext, aName); 27.153 + CheckError(); 27.154 + return res; 27.155 + } 27.156 + 27.157 + /// Wrapper for ctmGetUVMapString() 27.158 + const char * GetUVMapString(CTMenum aUVMap, CTMenum aProperty) 27.159 + { 27.160 + const char * res = ctmGetUVMapString(mContext, aUVMap, aProperty); 27.161 + CheckError(); 27.162 + return res; 27.163 + } 27.164 + 27.165 + /// Wrapper for ctmGetUVMapFloat() 27.166 + CTMfloat GetUVMapFloat(CTMenum aUVMap, CTMenum aProperty) 27.167 + { 27.168 + CTMfloat res = ctmGetUVMapFloat(mContext, aUVMap, aProperty); 27.169 + CheckError(); 27.170 + return res; 27.171 + } 27.172 + 27.173 + /// Wrapper for ctmGetNamedAttribMap() 27.174 + CTMenum GetNamedAttribMap(const char * aName) 27.175 + { 27.176 + CTMenum res = ctmGetNamedAttribMap(mContext, aName); 27.177 + CheckError(); 27.178 + return res; 27.179 + } 27.180 + 27.181 + /// Wrapper for ctmGetAttribMapString() 27.182 + const char * GetAttribMapString(CTMenum aAttribMap, CTMenum aProperty) 27.183 + { 27.184 + const char * res = ctmGetAttribMapString(mContext, aAttribMap, aProperty); 27.185 + CheckError(); 27.186 + return res; 27.187 + } 27.188 + 27.189 + /// Wrapper for ctmGetAttribMapFloat() 27.190 + CTMfloat GetAttribMapFloat(CTMenum aAttribMap, CTMenum aProperty) 27.191 + { 27.192 + CTMfloat res = ctmGetAttribMapFloat(mContext, aAttribMap, aProperty); 27.193 + CheckError(); 27.194 + return res; 27.195 + } 27.196 + 27.197 + /// Wrapper for ctmGetString() 27.198 + const char * GetString(CTMenum aProperty) 27.199 + { 27.200 + const char * res = ctmGetString(mContext, aProperty); 27.201 + CheckError(); 27.202 + return res; 27.203 + } 27.204 + 27.205 + /// Wrapper for ctmLoad() 27.206 + void Load(const char * aFileName) 27.207 + { 27.208 + ctmLoad(mContext, aFileName); 27.209 + CheckError(); 27.210 + } 27.211 + 27.212 + /// Wrapper for ctmLoadCustom() 27.213 + void LoadCustom(CTMreadfn aReadFn, void * aUserData) 27.214 + { 27.215 + ctmLoadCustom(mContext, aReadFn, aUserData); 27.216 + CheckError(); 27.217 + } 27.218 + 27.219 + // You can not copy nor assign from one CTMimporter object to another, since 27.220 + // the object contains hidden state. By declaring these dummy prototypes 27.221 + // without an implementation, you will at least get linker errors if you try 27.222 + // to copy or assign a CTMimporter object. 27.223 + CTMimporter(const CTMimporter& v); 27.224 + CTMimporter& operator=(const CTMimporter& v); 27.225 +}; 27.226 + 27.227 + 27.228 +/// OpenCTM exporter class. This is a C++ wrapper class for an OpenCTM export 27.229 +/// context. Usage example: 27.230 +/// @code 27.231 +/// void MySaveFile(CTMuint aVertCount, CTMuint aTriCount, CTMfloat * aVertices, 27.232 +/// CTMuint * aIndices, const char * aFileName) 27.233 +/// { 27.234 +/// // Create a new OpenCTM exporter object 27.235 +/// CTMexporter ctm; 27.236 +/// 27.237 +/// // Define our mesh representation to OpenCTM (store references to it in 27.238 +/// // the context) 27.239 +/// ctm.DefineMesh(aVertices, aVertCount, aIndices, aTriCount, NULL); 27.240 +/// 27.241 +/// // Save the OpenCTM file 27.242 +/// ctm.Save(aFileName); 27.243 +/// } 27.244 +/// @endcode 27.245 + 27.246 +class CTMexporter { 27.247 + private: 27.248 + /// The OpenCTM context handle. 27.249 + CTMcontext mContext; 27.250 + 27.251 + /// Check for OpenCTM errors, and throw an exception if an error has 27.252 + /// occured. 27.253 + void CheckError() 27.254 + { 27.255 + CTMenum err = ctmGetError(mContext); 27.256 + if(err != CTM_NONE) 27.257 + throw ctm_error(err); 27.258 + } 27.259 + 27.260 + public: 27.261 + /// Constructor 27.262 + CTMexporter() 27.263 + { 27.264 + mContext = ctmNewContext(CTM_EXPORT); 27.265 + } 27.266 + 27.267 + /// Destructor 27.268 + ~CTMexporter() 27.269 + { 27.270 + ctmFreeContext(mContext); 27.271 + } 27.272 + 27.273 + /// Wrapper for ctmCompressionMethod() 27.274 + void CompressionMethod(CTMenum aMethod) 27.275 + { 27.276 + ctmCompressionMethod(mContext, aMethod); 27.277 + CheckError(); 27.278 + } 27.279 + 27.280 + /// Wrapper for ctmCompressionLevel() 27.281 + void CompressionLevel(CTMuint aLevel) 27.282 + { 27.283 + ctmCompressionLevel(mContext, aLevel); 27.284 + CheckError(); 27.285 + } 27.286 + 27.287 + /// Wrapper for ctmVertexPrecision() 27.288 + void VertexPrecision(CTMfloat aPrecision) 27.289 + { 27.290 + ctmVertexPrecision(mContext, aPrecision); 27.291 + CheckError(); 27.292 + } 27.293 + 27.294 + /// Wrapper for ctmVertexPrecisionRel() 27.295 + void VertexPrecisionRel(CTMfloat aRelPrecision) 27.296 + { 27.297 + ctmVertexPrecisionRel(mContext, aRelPrecision); 27.298 + CheckError(); 27.299 + } 27.300 + 27.301 + /// Wrapper for ctmNormalPrecision() 27.302 + void NormalPrecision(CTMfloat aPrecision) 27.303 + { 27.304 + ctmNormalPrecision(mContext, aPrecision); 27.305 + CheckError(); 27.306 + } 27.307 + 27.308 + /// Wrapper for ctmUVCoordPrecision() 27.309 + void UVCoordPrecision(CTMenum aUVMap, CTMfloat aPrecision) 27.310 + { 27.311 + ctmUVCoordPrecision(mContext, aUVMap, aPrecision); 27.312 + CheckError(); 27.313 + } 27.314 + 27.315 + /// Wrapper for ctmAttribPrecision() 27.316 + void AttribPrecision(CTMenum aAttribMap, CTMfloat aPrecision) 27.317 + { 27.318 + ctmAttribPrecision(mContext, aAttribMap, aPrecision); 27.319 + CheckError(); 27.320 + } 27.321 + 27.322 + /// Wrapper for ctmFileComment() 27.323 + void FileComment(const char * aFileComment) 27.324 + { 27.325 + ctmFileComment(mContext, aFileComment); 27.326 + CheckError(); 27.327 + } 27.328 + 27.329 + /// Wrapper for ctmDefineMesh() 27.330 + void DefineMesh(const CTMfloat * aVertices, CTMuint aVertexCount, 27.331 + const CTMuint * aIndices, CTMuint aTriangleCount, 27.332 + const CTMfloat * aNormals) 27.333 + { 27.334 + ctmDefineMesh(mContext, aVertices, aVertexCount, aIndices, aTriangleCount, 27.335 + aNormals); 27.336 + CheckError(); 27.337 + } 27.338 + 27.339 + /// Wrapper for ctmAddUVMap() 27.340 + CTMenum AddUVMap(const CTMfloat * aUVCoords, const char * aName, 27.341 + const char * aFileName) 27.342 + { 27.343 + CTMenum res = ctmAddUVMap(mContext, aUVCoords, aName, aFileName); 27.344 + CheckError(); 27.345 + return res; 27.346 + } 27.347 + 27.348 + /// Wrapper for ctmAddAttribMap() 27.349 + CTMenum AddAttribMap(const CTMfloat * aAttribValues, const char * aName) 27.350 + { 27.351 + CTMenum res = ctmAddAttribMap(mContext, aAttribValues, aName); 27.352 + CheckError(); 27.353 + return res; 27.354 + } 27.355 + 27.356 + /// Wrapper for ctmSave() 27.357 + void Save(const char * aFileName) 27.358 + { 27.359 + ctmSave(mContext, aFileName); 27.360 + CheckError(); 27.361 + } 27.362 + 27.363 + /// Wrapper for ctmSaveCustom() 27.364 + void SaveCustom(CTMwritefn aWriteFn, void * aUserData) 27.365 + { 27.366 + ctmSaveCustom(mContext, aWriteFn, aUserData); 27.367 + CheckError(); 27.368 + } 27.369 + 27.370 + // You can not copy nor assign from one CTMexporter object to another, since 27.371 + // the object contains hidden state. By declaring these dummy prototypes 27.372 + // without an implementation, you will at least get linker errors if you try 27.373 + // to copy or assign a CTMexporter object. 27.374 + CTMexporter(const CTMexporter& v); 27.375 + CTMexporter& operator=(const CTMexporter& v); 27.376 +}; 27.377 + 27.378 +#endif // __OPENCTMPP_H_ 27.379 + 27.380 +#endif // OPENCTM_NO_CPP
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/libs/openctm/stream.c Thu Sep 26 04:47:05 2013 +0300 28.3 @@ -0,0 +1,512 @@ 28.4 +//----------------------------------------------------------------------------- 28.5 +// Product: OpenCTM 28.6 +// File: stream.c 28.7 +// Description: Stream I/O functions. 28.8 +//----------------------------------------------------------------------------- 28.9 +// Copyright (c) 2009-2010 Marcus Geelnard 28.10 +// 28.11 +// This software is provided 'as-is', without any express or implied 28.12 +// warranty. In no event will the authors be held liable for any damages 28.13 +// arising from the use of this software. 28.14 +// 28.15 +// Permission is granted to anyone to use this software for any purpose, 28.16 +// including commercial applications, and to alter it and redistribute it 28.17 +// freely, subject to the following restrictions: 28.18 +// 28.19 +// 1. The origin of this software must not be misrepresented; you must not 28.20 +// claim that you wrote the original software. If you use this software 28.21 +// in a product, an acknowledgment in the product documentation would be 28.22 +// appreciated but is not required. 28.23 +// 28.24 +// 2. Altered source versions must be plainly marked as such, and must not 28.25 +// be misrepresented as being the original software. 28.26 +// 28.27 +// 3. This notice may not be removed or altered from any source 28.28 +// distribution. 28.29 +//----------------------------------------------------------------------------- 28.30 + 28.31 +#include <stdlib.h> 28.32 +#include <string.h> 28.33 +#include <LzmaLib.h> 28.34 +#include "openctm.h" 28.35 +#include "internal.h" 28.36 + 28.37 +#ifdef __DEBUG_ 28.38 +#include <stdio.h> 28.39 +#endif 28.40 + 28.41 +//----------------------------------------------------------------------------- 28.42 +// _ctmStreamRead() - Read data from a stream. 28.43 +//----------------------------------------------------------------------------- 28.44 +CTMuint _ctmStreamRead(_CTMcontext * self, void * aBuf, CTMuint aCount) 28.45 +{ 28.46 + if(!self->mUserData || !self->mReadFn) 28.47 + return 0; 28.48 + 28.49 + return self->mReadFn(aBuf, aCount, self->mUserData); 28.50 +} 28.51 + 28.52 +//----------------------------------------------------------------------------- 28.53 +// _ctmStreamWrite() - Write data to a stream. 28.54 +//----------------------------------------------------------------------------- 28.55 +CTMuint _ctmStreamWrite(_CTMcontext * self, void * aBuf, CTMuint aCount) 28.56 +{ 28.57 + if(!self->mUserData || !self->mWriteFn) 28.58 + return 0; 28.59 + 28.60 + return self->mWriteFn(aBuf, aCount, self->mUserData); 28.61 +} 28.62 + 28.63 +//----------------------------------------------------------------------------- 28.64 +// _ctmStreamReadUINT() - Read an unsigned integer from a stream in a machine 28.65 +// endian independent manner (for portability). 28.66 +//----------------------------------------------------------------------------- 28.67 +CTMuint _ctmStreamReadUINT(_CTMcontext * self) 28.68 +{ 28.69 + unsigned char buf[4]; 28.70 + _ctmStreamRead(self, (void *) buf, 4); 28.71 + return ((CTMuint) buf[0]) | 28.72 + (((CTMuint) buf[1]) << 8) | 28.73 + (((CTMuint) buf[2]) << 16) | 28.74 + (((CTMuint) buf[3]) << 24); 28.75 +} 28.76 + 28.77 +//----------------------------------------------------------------------------- 28.78 +// _ctmStreamWriteUINT() - Write an unsigned integer to a stream in a machine 28.79 +// endian independent manner (for portability). 28.80 +//----------------------------------------------------------------------------- 28.81 +void _ctmStreamWriteUINT(_CTMcontext * self, CTMuint aValue) 28.82 +{ 28.83 + unsigned char buf[4]; 28.84 + buf[0] = aValue & 0x000000ff; 28.85 + buf[1] = (aValue >> 8) & 0x000000ff; 28.86 + buf[2] = (aValue >> 16) & 0x000000ff; 28.87 + buf[3] = (aValue >> 24) & 0x000000ff; 28.88 + _ctmStreamWrite(self, (void *) buf, 4); 28.89 +} 28.90 + 28.91 +//----------------------------------------------------------------------------- 28.92 +// _ctmStreamReadFLOAT() - Read a floating point value from a stream in a 28.93 +// machine endian independent manner (for portability). 28.94 +//----------------------------------------------------------------------------- 28.95 +CTMfloat _ctmStreamReadFLOAT(_CTMcontext * self) 28.96 +{ 28.97 + union { 28.98 + CTMfloat f; 28.99 + CTMuint i; 28.100 + } u; 28.101 + u.i = _ctmStreamReadUINT(self); 28.102 + return u.f; 28.103 +} 28.104 + 28.105 +//----------------------------------------------------------------------------- 28.106 +// _ctmStreamWriteFLOAT() - Write a floating point value to a stream in a 28.107 +// machine endian independent manner (for portability). 28.108 +//----------------------------------------------------------------------------- 28.109 +void _ctmStreamWriteFLOAT(_CTMcontext * self, CTMfloat aValue) 28.110 +{ 28.111 + union { 28.112 + CTMfloat f; 28.113 + CTMuint i; 28.114 + } u; 28.115 + u.f = aValue; 28.116 + _ctmStreamWriteUINT(self, u.i); 28.117 +} 28.118 + 28.119 +//----------------------------------------------------------------------------- 28.120 +// _ctmStreamReadSTRING() - Read a string value from a stream. The format of 28.121 +// the string in the stream is: an unsigned integer (string length) followed by 28.122 +// the string (without null termination). 28.123 +//----------------------------------------------------------------------------- 28.124 +void _ctmStreamReadSTRING(_CTMcontext * self, char ** aValue) 28.125 +{ 28.126 + CTMuint len; 28.127 + 28.128 + // Clear the old string 28.129 + if(*aValue) 28.130 + { 28.131 + free(*aValue); 28.132 + *aValue = (char *) 0; 28.133 + } 28.134 + 28.135 + // Get string length 28.136 + len = _ctmStreamReadUINT(self); 28.137 + 28.138 + // Read string 28.139 + if(len > 0) 28.140 + { 28.141 + *aValue = (char *) malloc(len + 1); 28.142 + if(*aValue) 28.143 + { 28.144 + _ctmStreamRead(self, (void *) *aValue, len); 28.145 + (*aValue)[len] = 0; 28.146 + } 28.147 + } 28.148 +} 28.149 + 28.150 +//----------------------------------------------------------------------------- 28.151 +// _ctmStreamWriteSTRING() - Write a string value to a stream. The format of 28.152 +// the string in the stream is: an unsigned integer (string length) followed by 28.153 +// the string (without null termination). 28.154 +//----------------------------------------------------------------------------- 28.155 +void _ctmStreamWriteSTRING(_CTMcontext * self, const char * aValue) 28.156 +{ 28.157 + CTMuint len; 28.158 + 28.159 + // Get string length 28.160 + if(aValue) 28.161 + len = strlen(aValue); 28.162 + else 28.163 + len = 0; 28.164 + 28.165 + // Write string length 28.166 + _ctmStreamWriteUINT(self, len); 28.167 + 28.168 + // Write string 28.169 + if(len > 0) 28.170 + _ctmStreamWrite(self, (void *) aValue, len); 28.171 +} 28.172 + 28.173 +//----------------------------------------------------------------------------- 28.174 +// _ctmStreamReadPackedInts() - Read an compressed binary integer data array 28.175 +// from a stream, and uncompress it. 28.176 +//----------------------------------------------------------------------------- 28.177 +int _ctmStreamReadPackedInts(_CTMcontext * self, CTMint * aData, 28.178 + CTMuint aCount, CTMuint aSize, CTMint aSignedInts) 28.179 +{ 28.180 + size_t packedSize, unpackedSize; 28.181 + CTMuint i, k, x; 28.182 + CTMint value; 28.183 + unsigned char * packed, * tmp; 28.184 + unsigned char props[5]; 28.185 + int lzmaRes; 28.186 + 28.187 + // Read packed data size from the stream 28.188 + packedSize = (size_t) _ctmStreamReadUINT(self); 28.189 + 28.190 + // Read LZMA compression props from the stream 28.191 + _ctmStreamRead(self, (void *) props, 5); 28.192 + 28.193 + // Allocate memory and read the packed data from the stream 28.194 + packed = (unsigned char *) malloc(packedSize); 28.195 + if(!packed) 28.196 + { 28.197 + self->mError = CTM_OUT_OF_MEMORY; 28.198 + return CTM_FALSE; 28.199 + } 28.200 + _ctmStreamRead(self, (void *) packed, packedSize); 28.201 + 28.202 + // Allocate memory for interleaved array 28.203 + tmp = (unsigned char *) malloc(aCount * aSize * 4); 28.204 + if(!tmp) 28.205 + { 28.206 + free(packed); 28.207 + self->mError = CTM_OUT_OF_MEMORY; 28.208 + return CTM_FALSE; 28.209 + } 28.210 + 28.211 + // Uncompress 28.212 + unpackedSize = aCount * aSize * 4; 28.213 + lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed, 28.214 + &packedSize, props, 5); 28.215 + 28.216 + // Free the packed array 28.217 + free(packed); 28.218 + 28.219 + // Error? 28.220 + if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4)) 28.221 + { 28.222 + self->mError = CTM_LZMA_ERROR; 28.223 + free(tmp); 28.224 + return CTM_FALSE; 28.225 + } 28.226 + 28.227 + // Convert interleaved array to integers 28.228 + for(i = 0; i < aCount; ++ i) 28.229 + { 28.230 + for(k = 0; k < aSize; ++ k) 28.231 + { 28.232 + value = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] | 28.233 + (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) | 28.234 + (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) | 28.235 + (((CTMint) tmp[i + k * aCount]) << 24); 28.236 + // Convert signed magnitude to two's complement? 28.237 + if(aSignedInts) 28.238 + { 28.239 + x = (CTMuint) value; 28.240 + value = (x & 1) ? -(CTMint)((x + 1) >> 1) : (CTMint)(x >> 1); 28.241 + } 28.242 + aData[i * aSize + k] = value; 28.243 + } 28.244 + } 28.245 + 28.246 + // Free the interleaved array 28.247 + free(tmp); 28.248 + 28.249 + return CTM_TRUE; 28.250 +} 28.251 + 28.252 +//----------------------------------------------------------------------------- 28.253 +// _ctmStreamWritePackedInts() - Compress a binary integer data array, and 28.254 +// write it to a stream. 28.255 +//----------------------------------------------------------------------------- 28.256 +int _ctmStreamWritePackedInts(_CTMcontext * self, CTMint * aData, 28.257 + CTMuint aCount, CTMuint aSize, CTMint aSignedInts) 28.258 +{ 28.259 + int lzmaRes, lzmaAlgo; 28.260 + CTMuint i, k; 28.261 + CTMint value; 28.262 + size_t bufSize, outPropsSize; 28.263 + unsigned char * packed, outProps[5], *tmp; 28.264 +#ifdef __DEBUG_ 28.265 + CTMuint negCount = 0; 28.266 +#endif 28.267 + 28.268 + // Allocate memory for interleaved array 28.269 + tmp = (unsigned char *) malloc(aCount * aSize * 4); 28.270 + if(!tmp) 28.271 + { 28.272 + self->mError = CTM_OUT_OF_MEMORY; 28.273 + return CTM_FALSE; 28.274 + } 28.275 + 28.276 + // Convert integers to an interleaved array 28.277 + for(i = 0; i < aCount; ++ i) 28.278 + { 28.279 + for(k = 0; k < aSize; ++ k) 28.280 + { 28.281 + value = aData[i * aSize + k]; 28.282 + // Convert two's complement to signed magnitude? 28.283 + if(aSignedInts) 28.284 + value = value < 0 ? -1 - (value << 1) : value << 1; 28.285 +#ifdef __DEBUG_ 28.286 + else if(value < 0) 28.287 + ++ negCount; 28.288 +#endif 28.289 + tmp[i + k * aCount + 3 * aCount * aSize] = value & 0x000000ff; 28.290 + tmp[i + k * aCount + 2 * aCount * aSize] = (value >> 8) & 0x000000ff; 28.291 + tmp[i + k * aCount + aCount * aSize] = (value >> 16) & 0x000000ff; 28.292 + tmp[i + k * aCount] = (value >> 24) & 0x000000ff; 28.293 + } 28.294 + } 28.295 + 28.296 + // Allocate memory for the packed data 28.297 + bufSize = 1000 + aCount * aSize * 4; 28.298 + packed = (unsigned char *) malloc(bufSize); 28.299 + if(!packed) 28.300 + { 28.301 + free(tmp); 28.302 + self->mError = CTM_OUT_OF_MEMORY; 28.303 + return CTM_FALSE; 28.304 + } 28.305 + 28.306 + // Call LZMA to compress 28.307 + outPropsSize = 5; 28.308 + lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1); 28.309 + lzmaRes = LzmaCompress(packed, 28.310 + &bufSize, 28.311 + (const unsigned char *) tmp, 28.312 + aCount * aSize * 4, 28.313 + outProps, 28.314 + &outPropsSize, 28.315 + self->mCompressionLevel, // Level (0-9) 28.316 + 0, -1, -1, -1, -1, -1, // Default values (set by level) 28.317 + lzmaAlgo // Algorithm (0 = fast, 1 = normal) 28.318 + ); 28.319 + 28.320 + // Free temporary array 28.321 + free(tmp); 28.322 + 28.323 + // Error? 28.324 + if(lzmaRes != SZ_OK) 28.325 + { 28.326 + self->mError = CTM_LZMA_ERROR; 28.327 + free(packed); 28.328 + return CTM_FALSE; 28.329 + } 28.330 + 28.331 +#ifdef __DEBUG_ 28.332 + printf("%d->%d bytes (%d negative words)\n", aCount * aSize * 4, (int) bufSize, negCount); 28.333 +#endif 28.334 + 28.335 + // Write packed data size to the stream 28.336 + _ctmStreamWriteUINT(self, (CTMuint) bufSize); 28.337 + 28.338 + // Write LZMA compression props to the stream 28.339 + _ctmStreamWrite(self, (void *) outProps, 5); 28.340 + 28.341 + // Write the packed data to the stream 28.342 + _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize); 28.343 + 28.344 + // Free the packed data 28.345 + free(packed); 28.346 + 28.347 + return CTM_TRUE; 28.348 +} 28.349 + 28.350 +//----------------------------------------------------------------------------- 28.351 +// _ctmStreamReadPackedFloats() - Read an compressed binary float data array 28.352 +// from a stream, and uncompress it. 28.353 +//----------------------------------------------------------------------------- 28.354 +int _ctmStreamReadPackedFloats(_CTMcontext * self, CTMfloat * aData, 28.355 + CTMuint aCount, CTMuint aSize) 28.356 +{ 28.357 + CTMuint i, k; 28.358 + size_t packedSize, unpackedSize; 28.359 + union { 28.360 + CTMfloat f; 28.361 + CTMint i; 28.362 + } value; 28.363 + unsigned char * packed, * tmp; 28.364 + unsigned char props[5]; 28.365 + int lzmaRes; 28.366 + 28.367 + // Read packed data size from the stream 28.368 + packedSize = (size_t) _ctmStreamReadUINT(self); 28.369 + 28.370 + // Read LZMA compression props from the stream 28.371 + _ctmStreamRead(self, (void *) props, 5); 28.372 + 28.373 + // Allocate memory and read the packed data from the stream 28.374 + packed = (unsigned char *) malloc(packedSize); 28.375 + if(!packed) 28.376 + { 28.377 + self->mError = CTM_OUT_OF_MEMORY; 28.378 + return CTM_FALSE; 28.379 + } 28.380 + _ctmStreamRead(self, (void *) packed, packedSize); 28.381 + 28.382 + // Allocate memory for interleaved array 28.383 + tmp = (unsigned char *) malloc(aCount * aSize * 4); 28.384 + if(!tmp) 28.385 + { 28.386 + free(packed); 28.387 + self->mError = CTM_OUT_OF_MEMORY; 28.388 + return CTM_FALSE; 28.389 + } 28.390 + 28.391 + // Uncompress 28.392 + unpackedSize = aCount * aSize * 4; 28.393 + lzmaRes = LzmaUncompress(tmp, &unpackedSize, packed, 28.394 + &packedSize, props, 5); 28.395 + 28.396 + // Free the packed array 28.397 + free(packed); 28.398 + 28.399 + // Error? 28.400 + if((lzmaRes != SZ_OK) || (unpackedSize != aCount * aSize * 4)) 28.401 + { 28.402 + self->mError = CTM_LZMA_ERROR; 28.403 + free(tmp); 28.404 + return CTM_FALSE; 28.405 + } 28.406 + 28.407 + // Convert interleaved array to floats 28.408 + for(i = 0; i < aCount; ++ i) 28.409 + { 28.410 + for(k = 0; k < aSize; ++ k) 28.411 + { 28.412 + value.i = (CTMint) tmp[i + k * aCount + 3 * aCount * aSize] | 28.413 + (((CTMint) tmp[i + k * aCount + 2 * aCount * aSize]) << 8) | 28.414 + (((CTMint) tmp[i + k * aCount + aCount * aSize]) << 16) | 28.415 + (((CTMint) tmp[i + k * aCount]) << 24); 28.416 + aData[i * aSize + k] = value.f; 28.417 + } 28.418 + } 28.419 + 28.420 + // Free the interleaved array 28.421 + free(tmp); 28.422 + 28.423 + return CTM_TRUE; 28.424 +} 28.425 + 28.426 +//----------------------------------------------------------------------------- 28.427 +// _ctmStreamWritePackedFloats() - Compress a binary float data array, and 28.428 +// write it to a stream. 28.429 +//----------------------------------------------------------------------------- 28.430 +int _ctmStreamWritePackedFloats(_CTMcontext * self, CTMfloat * aData, 28.431 + CTMuint aCount, CTMuint aSize) 28.432 +{ 28.433 + int lzmaRes, lzmaAlgo; 28.434 + CTMuint i, k; 28.435 + union { 28.436 + CTMfloat f; 28.437 + CTMint i; 28.438 + } value; 28.439 + size_t bufSize, outPropsSize; 28.440 + unsigned char * packed, outProps[5], *tmp; 28.441 + 28.442 + // Allocate memory for interleaved array 28.443 + tmp = (unsigned char *) malloc(aCount * aSize * 4); 28.444 + if(!tmp) 28.445 + { 28.446 + self->mError = CTM_OUT_OF_MEMORY; 28.447 + return CTM_FALSE; 28.448 + } 28.449 + 28.450 + // Convert floats to an interleaved array 28.451 + for(i = 0; i < aCount; ++ i) 28.452 + { 28.453 + for(k = 0; k < aSize; ++ k) 28.454 + { 28.455 + value.f = aData[i * aSize + k]; 28.456 + tmp[i + k * aCount + 3 * aCount * aSize] = value.i & 0x000000ff; 28.457 + tmp[i + k * aCount + 2 * aCount * aSize] = (value.i >> 8) & 0x000000ff; 28.458 + tmp[i + k * aCount + aCount * aSize] = (value.i >> 16) & 0x000000ff; 28.459 + tmp[i + k * aCount] = (value.i >> 24) & 0x000000ff; 28.460 + } 28.461 + } 28.462 + 28.463 + // Allocate memory for the packed data 28.464 + bufSize = 1000 + aCount * aSize * 4; 28.465 + packed = (unsigned char *) malloc(bufSize); 28.466 + if(!packed) 28.467 + { 28.468 + free(tmp); 28.469 + self->mError = CTM_OUT_OF_MEMORY; 28.470 + return CTM_FALSE; 28.471 + } 28.472 + 28.473 + // Call LZMA to compress 28.474 + outPropsSize = 5; 28.475 + lzmaAlgo = (self->mCompressionLevel < 1 ? 0 : 1); 28.476 + lzmaRes = LzmaCompress(packed, 28.477 + &bufSize, 28.478 + (const unsigned char *) tmp, 28.479 + aCount * aSize * 4, 28.480 + outProps, 28.481 + &outPropsSize, 28.482 + self->mCompressionLevel, // Level (0-9) 28.483 + 0, -1, -1, -1, -1, -1, // Default values (set by level) 28.484 + lzmaAlgo // Algorithm (0 = fast, 1 = normal) 28.485 + ); 28.486 + 28.487 + // Free temporary array 28.488 + free(tmp); 28.489 + 28.490 + // Error? 28.491 + if(lzmaRes != SZ_OK) 28.492 + { 28.493 + self->mError = CTM_LZMA_ERROR; 28.494 + free(packed); 28.495 + return CTM_FALSE; 28.496 + } 28.497 + 28.498 +#ifdef __DEBUG_ 28.499 + printf("%d->%d bytes\n", aCount * aSize * 4, (int) bufSize); 28.500 +#endif 28.501 + 28.502 + // Write packed data size to the stream 28.503 + _ctmStreamWriteUINT(self, (CTMuint) bufSize); 28.504 + 28.505 + // Write LZMA compression props to the stream 28.506 + _ctmStreamWrite(self, (void *) outProps, 5); 28.507 + 28.508 + // Write the packed data to the stream 28.509 + _ctmStreamWrite(self, (void *) packed, (CTMuint) bufSize); 28.510 + 28.511 + // Free the packed data 28.512 + free(packed); 28.513 + 28.514 + return CTM_TRUE; 28.515 +}
29.1 --- a/src/chunk.h Tue Sep 10 15:29:45 2013 +0300 29.2 +++ b/src/chunk.h Thu Sep 26 04:47:05 2013 +0300 29.3 @@ -18,33 +18,28 @@ 29.4 // --- first level chunks --- 29.5 // children of CNK_SCENE 29.6 CNK_ENV, // environmental parameters 29.7 - CNK_MTL_LIST, // material library 29.8 - CNK_MESH_LIST, // all the meshes hang under this chunk 29.9 - CNK_LIGHT_LIST, // likewise for lights 29.10 - CNK_CAMERA_LIST, // likewise for cameras 29.11 - CNK_NODE_LIST, // likewise for nodes 29.12 + CNK_MTL, // material 29.13 + CNK_MESH, 29.14 + CNK_LIGHT, 29.15 + CNK_CAMERA, 29.16 + CNK_NODE, 29.17 29.18 // --- second level chunks --- 29.19 // children of CNK_ENV 29.20 CNK_ENV_AMBIENT, // ambient color, contains a single CNK_FLOAT3 29.21 CNK_ENV_FOG, 29.22 29.23 - // children of CNK_*_LIST 29.24 - CNK_MTL, 29.25 - CNK_MESH, 29.26 - CNK_LIGHT, 29.27 - CNK_CAMERA, 29.28 - CNK_NODE, 29.29 - 29.30 // --- third level chunks --- 29.31 // children of CNK_FOG 29.32 CNK_FOG_COLOR, // fog color, contains a single CNK_FLOAT3 29.33 - CNK_FOG_EXP, // fog exponent, contains a single CNK_REAL 29.34 + CNK_FOG_EXP, // fog exponent, contains a single CNK_FLOAT 29.35 29.36 // children of CNK_MTL 29.37 + CNK_MTL_NAME, // has a single CNK_STRING 29.38 CNK_MTL_ATTR, // material attribute, has a CNK_STRING for its name, 29.39 // a CNK_MTL_ATTR_VAL, and optionally a CNK_MTL_ATTR_MAP 29.40 // children of CNK_MTL_ATTR 29.41 + CNK_MTL_ATTR_NAME, // has a single CNK_STRING 29.42 CNK_MTL_ATTR_VAL, // can have a single CNK_FLOAT, CNK_FLOAT3, or CNK_FLOAT4 29.43 CNK_MTL_ATTR_MAP, // has a single CNK_STRING 29.44 29.45 @@ -60,6 +55,7 @@ 29.46 CNK_MESH_COLOR_LIST, // has a series of CNK_FLOAT4 chunks 29.47 CNK_MESH_BONES_LIST, // has a series of CNK_INT or CNK_STRING chunks identifying the bone nodes 29.48 CNK_MESH_FACE_LIST, // has a series of CNK_FACE chunks 29.49 + CNK_MESH_FILE, // optionally mesh data may be in another file, has a CNK_STRING filename 29.50 29.51 // child of CNK_MESH_FACE_LIST 29.52 CNK_MESH_FACE, // has three CNK_INT chunks 29.53 @@ -90,14 +86,14 @@ 29.54 CNK_NODE_LIGHT, // same as CNK_NODE_MESH 29.55 CNK_NODE_CAMERA, // same as CNK_NODE_MESH 29.56 29.57 - CNK_NODE_POS, // has a CNK_VEC3, position vector 29.58 - CNK_NODE_ROT, // has a CNK_VEC4, rotation quaternion (x, y, z imaginary, w real) 29.59 - CNK_NODE_SCALE, // has a CNK_VEC3, scaling 29.60 - CNK_NODE_PIVOT, // has a CNK_VEC3, pivot point 29.61 + CNK_NODE_POS, // has a CNK_FLOAT3, position vector 29.62 + CNK_NODE_ROT, // has a CNK_FLOAT4, rotation quaternion (x, y, z imaginary, w real) 29.63 + CNK_NODE_SCALE, // has a CNK_FLOAT3, scaling 29.64 + CNK_NODE_PIVOT, // has a CNK_FLOAT3, pivot point 29.65 29.66 - CNK_NODE_MATRIX0, // has a CNK_VEC4, first matrix row (4x3) 29.67 - CNK_NODE_MATRXI1, // has a CNK_VEC4, second matrix row (4x3) 29.68 - CNK_NODE_MATRIX2, // has a CNK_VEC4, third matrix row (4x3) 29.69 + CNK_NODE_MATRIX0, // has a CNK_FLOAT4, first matrix row (4x3) 29.70 + CNK_NODE_MATRXI1, // has a CNK_FLOAT4, second matrix row (4x3) 29.71 + CNK_NODE_MATRIX2, // has a CNK_FLOAT4, third matrix row (4x3) 29.72 29.73 MAX_NUM_CHUNKS 29.74 };
30.1 --- a/src/goat3d.cc Tue Sep 10 15:29:45 2013 +0300 30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 30.3 @@ -1,409 +0,0 @@ 30.4 -#include "goat3d.h" 30.5 -#include "goat3d_impl.h" 30.6 -#include "chunk.h" 30.7 - 30.8 -Scene::Scene() 30.9 - : name("unnamed"), ambient(0.05, 0.05, 0.05) 30.10 -{ 30.11 -} 30.12 - 30.13 -Scene::~Scene() 30.14 -{ 30.15 - clear(); 30.16 -} 30.17 - 30.18 -void Scene::clear() 30.19 -{ 30.20 - for(size_t i=0; i<materials.size(); i++) { 30.21 - delete materials[i]; 30.22 - } 30.23 - materials.clear(); 30.24 - 30.25 - for(size_t i=0; i<meshes.size(); i++) { 30.26 - delete meshes[i]; 30.27 - } 30.28 - meshes.clear(); 30.29 - 30.30 - for(size_t i=0; i<lights.size(); i++) { 30.31 - delete lights[i]; 30.32 - } 30.33 - lights.clear(); 30.34 - 30.35 - for(size_t i=0; i<cameras.size(); i++) { 30.36 - delete cameras[i]; 30.37 - } 30.38 - cameras.clear(); 30.39 - 30.40 - for(size_t i=0; i<nodes.size(); i++) { 30.41 - delete_node_tree(nodes[i]); 30.42 - } 30.43 - nodes.clear(); 30.44 - 30.45 - name = "unnamed"; 30.46 -} 30.47 - 30.48 -void Scene::set_name(const char *name) 30.49 -{ 30.50 - this->name = name; 30.51 -} 30.52 - 30.53 -const char *Scene::get_name() const 30.54 -{ 30.55 - return name.c_str(); 30.56 -} 30.57 - 30.58 -void Scene::set_ambient(const Vector3 &amb) 30.59 -{ 30.60 - ambient = amb; 30.61 -} 30.62 - 30.63 -const Vector3 &Scene::get_ambient() const 30.64 -{ 30.65 - return ambient; 30.66 -} 30.67 - 30.68 -void Scene::add_material(Material *mat) 30.69 -{ 30.70 - materials.push_back(mat); 30.71 -} 30.72 - 30.73 -Material *Scene::get_material(int idx) const 30.74 -{ 30.75 - return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0; 30.76 -} 30.77 - 30.78 -Material *Scene::get_material(const char *name) const 30.79 -{ 30.80 - for(size_t i=0; i<materials.size(); i++) { 30.81 - if(materials[i]->name == std::string(name)) { 30.82 - return materials[i]; 30.83 - } 30.84 - } 30.85 - return 0; 30.86 -} 30.87 - 30.88 -int Scene::get_material_count() const 30.89 -{ 30.90 - return (int)materials.size(); 30.91 -} 30.92 - 30.93 - 30.94 -void Scene::add_mesh(Mesh *mesh) 30.95 -{ 30.96 - meshes.push_back(mesh); 30.97 -} 30.98 - 30.99 -Mesh *Scene::get_mesh(int idx) const 30.100 -{ 30.101 - return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0; 30.102 -} 30.103 - 30.104 -Mesh *Scene::get_mesh(const char *name) const 30.105 -{ 30.106 - for(size_t i=0; i<meshes.size(); i++) { 30.107 - if(meshes[i]->name == std::string(name)) { 30.108 - return meshes[i]; 30.109 - } 30.110 - } 30.111 - return 0; 30.112 -} 30.113 - 30.114 -int Scene::get_mesh_count() const 30.115 -{ 30.116 - return (int)meshes.size(); 30.117 -} 30.118 - 30.119 - 30.120 -void Scene::add_light(Light *light) 30.121 -{ 30.122 - lights.push_back(light); 30.123 -} 30.124 - 30.125 -Light *Scene::get_light(int idx) const 30.126 -{ 30.127 - return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0; 30.128 -} 30.129 - 30.130 -Light *Scene::get_light(const char *name) const 30.131 -{ 30.132 - for(size_t i=0; i<lights.size(); i++) { 30.133 - if(lights[i]->name == std::string(name)) { 30.134 - return lights[i]; 30.135 - } 30.136 - } 30.137 - return 0; 30.138 -} 30.139 - 30.140 -int Scene::get_light_count() const 30.141 -{ 30.142 - return (int)lights.size(); 30.143 -} 30.144 - 30.145 - 30.146 -void Scene::add_camera(Camera *cam) 30.147 -{ 30.148 - cameras.push_back(cam); 30.149 -} 30.150 - 30.151 -Camera *Scene::get_camera(int idx) const 30.152 -{ 30.153 - return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0; 30.154 -} 30.155 - 30.156 -Camera *Scene::get_camera(const char *name) const 30.157 -{ 30.158 - for(size_t i=0; i<cameras.size(); i++) { 30.159 - if(cameras[i]->name == std::string(name)) { 30.160 - return cameras[i]; 30.161 - } 30.162 - } 30.163 - return 0; 30.164 -} 30.165 - 30.166 -int Scene::get_camera_count() const 30.167 -{ 30.168 - return (int)cameras.size(); 30.169 -} 30.170 - 30.171 - 30.172 -void Scene::add_node(Node *node) 30.173 -{ 30.174 - nodes.push_back(node); 30.175 -} 30.176 - 30.177 -Node *Scene::get_node(int idx) const 30.178 -{ 30.179 - return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0; 30.180 -} 30.181 - 30.182 -Node *Scene::get_node(const char *name) const 30.183 -{ 30.184 - for(size_t i=0; i<nodes.size(); i++) { 30.185 - if(strcmp(nodes[i]->get_name(), name) == 0) { 30.186 - return nodes[i]; 30.187 - } 30.188 - } 30.189 - return 0; 30.190 -} 30.191 - 30.192 -int Scene::get_node_count() const 30.193 -{ 30.194 - return (int)nodes.size(); 30.195 -} 30.196 - 30.197 - 30.198 -bool Scene::load(goat3d_io *io) 30.199 -{ 30.200 - return false; 30.201 -} 30.202 - 30.203 -static long save_env(const Scene *scn, long offset, goat3d_io *io); 30.204 -static long save_materials(const Scene *scn, long offset, goat3d_io *io); 30.205 -static long save_material(const Material *mat, long offset, goat3d_io *io); 30.206 -static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io); 30.207 -static long save_meshes(const Scene *scn, long offset, goat3d_io *io); 30.208 -static long save_lights(const Scene *scn, long offset, goat3d_io *io); 30.209 -static long save_cameras(const Scene *scn, long offset, goat3d_io *io); 30.210 -static long save_nodes(const Scene *scn, long offset, goat3d_io *io); 30.211 - 30.212 -static long write_chunk_float(int id, float val, long offs, goat3d_io *io); 30.213 -static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io); 30.214 -static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io); 30.215 - 30.216 -bool Scene::save(goat3d_io *io) const 30.217 -{ 30.218 - long res; 30.219 - 30.220 - ChunkHeader hdr; 30.221 - hdr.id = CNK_SCENE; 30.222 - hdr.size = sizeof hdr; 30.223 - 30.224 - if((res = save_env(this, hdr.size, io)) < 0) { 30.225 - return false; 30.226 - } 30.227 - hdr.size += res; 30.228 - 30.229 - if((res = save_materials(this, hdr.size, io)) < 0) { 30.230 - return false; 30.231 - } 30.232 - hdr.size += res; 30.233 - 30.234 - if((res = save_meshes(this, hdr.size, io)) < 0) { 30.235 - return false; 30.236 - } 30.237 - hdr.size += res; 30.238 - 30.239 - if((res = save_lights(this, hdr.size, io)) < 0) { 30.240 - return false; 30.241 - } 30.242 - hdr.size += res; 30.243 - 30.244 - if((res = save_cameras(this, hdr.size, io)) < 0) { 30.245 - return false; 30.246 - } 30.247 - hdr.size += res; 30.248 - 30.249 - if((res = save_nodes(this, hdr.size, io)) < 0) { 30.250 - return false; 30.251 - } 30.252 - hdr.size += res; 30.253 - 30.254 - // now go back and write the root chunk 30.255 - io->seek(0, SEEK_SET, io->cls); 30.256 - if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) { 30.257 - return false; 30.258 - } 30.259 - 30.260 - return true; 30.261 -} 30.262 - 30.263 - 30.264 -static long save_env(const Scene *scn, long offset, goat3d_io *io) 30.265 -{ 30.266 - long res; 30.267 - 30.268 - ChunkHeader hdr; 30.269 - hdr.id = CNK_ENV; 30.270 - hdr.size = sizeof hdr; 30.271 - 30.272 - if((res = write_chunk_float3(CNK_ENV_AMBIENT, scn->get_ambient(), offset, io)) < 0) { 30.273 - return -1; 30.274 - } 30.275 - hdr.size += res; 30.276 - 30.277 - // TODO add fog chunk 30.278 - 30.279 - io->seek(offset, SEEK_SET, io->cls); 30.280 - if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) { 30.281 - return -1; 30.282 - } 30.283 - return hdr.size; 30.284 -} 30.285 - 30.286 -static long save_materials(const Scene *scn, long offset, goat3d_io *io) 30.287 -{ 30.288 - long res; 30.289 - 30.290 - ChunkHeader hdr; 30.291 - hdr.id = CNK_MTL_LIST; 30.292 - hdr.size = sizeof hdr; 30.293 - 30.294 - for(int i=0; i<scn->get_material_count(); i++) { 30.295 - if((res = save_material(scn->get_material(i), offset + hdr.size, io)) < 0) { 30.296 - return -1; 30.297 - } 30.298 - hdr.size += res; 30.299 - } 30.300 - 30.301 - io->seek(offset, SEEK_SET, io->cls); 30.302 - if(io->write(&hdr, hdr.size, io->cls) < hdr.size) { 30.303 - return -1; 30.304 - } 30.305 - return hdr.size; 30.306 -} 30.307 - 30.308 -static long save_material(const Material *mat, long offset, goat3d_io *io) 30.309 -{ 30.310 - long res; 30.311 - 30.312 - ChunkHeader hdr; 30.313 - hdr.id = CNK_MTL; 30.314 - hdr.size = sizeof hdr; 30.315 - 30.316 - for(int i=0; i<mat->get_attrib_count(); i++) { 30.317 - const char *name = mat->get_attrib_name(i); 30.318 - if((res = save_mat_attrib(name, (*mat)[i], offset + hdr.size, io)) < 0) { 30.319 - return -1; 30.320 - } 30.321 - hdr.size += res; 30.322 - } 30.323 - 30.324 - io->seek(offset, SEEK_SET, io->cls); 30.325 - if(io->write(&hdr, hdr.size, io->cls) < hdr.size) { 30.326 - return -1; 30.327 - } 30.328 - return hdr.size; 30.329 -} 30.330 - 30.331 -static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io) 30.332 -{ 30.333 - long res; 30.334 - 30.335 - ChunkHeader hdr; 30.336 - hdr.id = CNK_MTL_ATTR; 30.337 - hdr.size = sizeof hdr; 30.338 - 30.339 - // TODO cont. 30.340 - return -1; 30.341 -} 30.342 - 30.343 -static long save_meshes(const Scene *scn, long offset, goat3d_io *io) 30.344 -{ 30.345 - return 0; 30.346 -} 30.347 - 30.348 -static long save_lights(const Scene *scn, long offset, goat3d_io *io) 30.349 -{ 30.350 - return 0; 30.351 -} 30.352 - 30.353 -static long save_cameras(const Scene *scn, long offset, goat3d_io *io) 30.354 -{ 30.355 - return 0; 30.356 -} 30.357 - 30.358 -static long save_nodes(const Scene *scn, long offset, goat3d_io *io) 30.359 -{ 30.360 - return 0; 30.361 -} 30.362 - 30.363 -static long write_chunk_float(int id, float val, long offs, goat3d_io *io) 30.364 -{ 30.365 - int size = sizeof(ChunkHeader) + sizeof val; 30.366 - char *buf = (char*)alloca(size); 30.367 - 30.368 - Chunk *c = (Chunk*)buf; 30.369 - c->hdr.id = id; 30.370 - c->hdr.size = size; 30.371 - *(float*)c->data = val; 30.372 - 30.373 - io->seek(offs, SEEK_SET, io->cls); 30.374 - if(io->write(buf, size, io->cls) < size) { 30.375 - return -1; 30.376 - } 30.377 - return size; 30.378 -} 30.379 - 30.380 -static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io) 30.381 -{ 30.382 - int size = sizeof(ChunkHeader) + sizeof vec; 30.383 - char *buf = (char*)alloca(size); 30.384 - 30.385 - Chunk *c = (Chunk*)buf; 30.386 - c->hdr.id = id; 30.387 - c->hdr.size = size; 30.388 - *(Vector3*)c->data = vec; 30.389 - 30.390 - io->seek(offs, SEEK_SET, io->cls); 30.391 - if(io->write(buf, size, io->cls) < size) { 30.392 - return -1; 30.393 - } 30.394 - return size; 30.395 -} 30.396 - 30.397 -static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io) 30.398 -{ 30.399 - int size = sizeof(ChunkHeader) + sizeof vec; 30.400 - char *buf = (char*)alloca(size); 30.401 - 30.402 - Chunk *c = (Chunk*)buf; 30.403 - c->hdr.id = id; 30.404 - c->hdr.size = size; 30.405 - *(Vector4*)c->data = vec; 30.406 - 30.407 - io->seek(offs, SEEK_SET, io->cls); 30.408 - if(io->write(buf, size, io->cls) < size) { 30.409 - return -1; 30.410 - } 30.411 - return size; 30.412 -}
31.1 --- a/src/goat3d_impl.h Tue Sep 10 15:29:45 2013 +0300 31.2 +++ b/src/goat3d_impl.h Thu Sep 26 04:47:05 2013 +0300 31.3 @@ -60,7 +60,12 @@ 31.4 31.5 bool load(goat3d_io *io); 31.6 bool save(goat3d_io *io) const; 31.7 + 31.8 + bool loadxml(goat3d_io *io); 31.9 + bool savexml(goat3d_io *io) const; 31.10 }; 31.11 31.12 +void io_fprintf(goat3d_io *io, const char *fmt, ...); 31.13 +void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap); 31.14 31.15 #endif // GOAT3D_IMPL_H_
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/src/goat3d_scene.cc Thu Sep 26 04:47:05 2013 +0300 32.3 @@ -0,0 +1,253 @@ 32.4 +#include <stdarg.h> 32.5 +#include "goat3d.h" 32.6 +#include "goat3d_impl.h" 32.7 +#include "chunk.h" 32.8 + 32.9 +Scene::Scene() 32.10 + : name("unnamed"), ambient(0.05, 0.05, 0.05) 32.11 +{ 32.12 +} 32.13 + 32.14 +Scene::~Scene() 32.15 +{ 32.16 + clear(); 32.17 +} 32.18 + 32.19 +void Scene::clear() 32.20 +{ 32.21 + for(size_t i=0; i<materials.size(); i++) { 32.22 + delete materials[i]; 32.23 + } 32.24 + materials.clear(); 32.25 + 32.26 + for(size_t i=0; i<meshes.size(); i++) { 32.27 + delete meshes[i]; 32.28 + } 32.29 + meshes.clear(); 32.30 + 32.31 + for(size_t i=0; i<lights.size(); i++) { 32.32 + delete lights[i]; 32.33 + } 32.34 + lights.clear(); 32.35 + 32.36 + for(size_t i=0; i<cameras.size(); i++) { 32.37 + delete cameras[i]; 32.38 + } 32.39 + cameras.clear(); 32.40 + 32.41 + for(size_t i=0; i<nodes.size(); i++) { 32.42 + delete_node_tree(nodes[i]); 32.43 + } 32.44 + nodes.clear(); 32.45 + 32.46 + name = "unnamed"; 32.47 +} 32.48 + 32.49 +void Scene::set_name(const char *name) 32.50 +{ 32.51 + this->name = name; 32.52 +} 32.53 + 32.54 +const char *Scene::get_name() const 32.55 +{ 32.56 + return name.c_str(); 32.57 +} 32.58 + 32.59 +void Scene::set_ambient(const Vector3 &amb) 32.60 +{ 32.61 + ambient = amb; 32.62 +} 32.63 + 32.64 +const Vector3 &Scene::get_ambient() const 32.65 +{ 32.66 + return ambient; 32.67 +} 32.68 + 32.69 +void Scene::add_material(Material *mat) 32.70 +{ 32.71 + materials.push_back(mat); 32.72 +} 32.73 + 32.74 +Material *Scene::get_material(int idx) const 32.75 +{ 32.76 + return idx >=0 && idx < (int)materials.size() ? materials[idx] : 0; 32.77 +} 32.78 + 32.79 +Material *Scene::get_material(const char *name) const 32.80 +{ 32.81 + for(size_t i=0; i<materials.size(); i++) { 32.82 + if(materials[i]->name == std::string(name)) { 32.83 + return materials[i]; 32.84 + } 32.85 + } 32.86 + return 0; 32.87 +} 32.88 + 32.89 +int Scene::get_material_count() const 32.90 +{ 32.91 + return (int)materials.size(); 32.92 +} 32.93 + 32.94 + 32.95 +void Scene::add_mesh(Mesh *mesh) 32.96 +{ 32.97 + meshes.push_back(mesh); 32.98 +} 32.99 + 32.100 +Mesh *Scene::get_mesh(int idx) const 32.101 +{ 32.102 + return idx >= 0 && idx < (int)meshes.size() ? meshes[idx] : 0; 32.103 +} 32.104 + 32.105 +Mesh *Scene::get_mesh(const char *name) const 32.106 +{ 32.107 + for(size_t i=0; i<meshes.size(); i++) { 32.108 + if(meshes[i]->name == std::string(name)) { 32.109 + return meshes[i]; 32.110 + } 32.111 + } 32.112 + return 0; 32.113 +} 32.114 + 32.115 +int Scene::get_mesh_count() const 32.116 +{ 32.117 + return (int)meshes.size(); 32.118 +} 32.119 + 32.120 + 32.121 +void Scene::add_light(Light *light) 32.122 +{ 32.123 + lights.push_back(light); 32.124 +} 32.125 + 32.126 +Light *Scene::get_light(int idx) const 32.127 +{ 32.128 + return idx >= 0 && idx < (int)lights.size() ? lights[idx] : 0; 32.129 +} 32.130 + 32.131 +Light *Scene::get_light(const char *name) const 32.132 +{ 32.133 + for(size_t i=0; i<lights.size(); i++) { 32.134 + if(lights[i]->name == std::string(name)) { 32.135 + return lights[i]; 32.136 + } 32.137 + } 32.138 + return 0; 32.139 +} 32.140 + 32.141 +int Scene::get_light_count() const 32.142 +{ 32.143 + return (int)lights.size(); 32.144 +} 32.145 + 32.146 + 32.147 +void Scene::add_camera(Camera *cam) 32.148 +{ 32.149 + cameras.push_back(cam); 32.150 +} 32.151 + 32.152 +Camera *Scene::get_camera(int idx) const 32.153 +{ 32.154 + return idx >= 0 && idx < (int)cameras.size() ? cameras[idx] : 0; 32.155 +} 32.156 + 32.157 +Camera *Scene::get_camera(const char *name) const 32.158 +{ 32.159 + for(size_t i=0; i<cameras.size(); i++) { 32.160 + if(cameras[i]->name == std::string(name)) { 32.161 + return cameras[i]; 32.162 + } 32.163 + } 32.164 + return 0; 32.165 +} 32.166 + 32.167 +int Scene::get_camera_count() const 32.168 +{ 32.169 + return (int)cameras.size(); 32.170 +} 32.171 + 32.172 + 32.173 +void Scene::add_node(Node *node) 32.174 +{ 32.175 + nodes.push_back(node); 32.176 +} 32.177 + 32.178 +Node *Scene::get_node(int idx) const 32.179 +{ 32.180 + return idx >= 0 && idx < (int)nodes.size() ? nodes[idx] : 0; 32.181 +} 32.182 + 32.183 +Node *Scene::get_node(const char *name) const 32.184 +{ 32.185 + for(size_t i=0; i<nodes.size(); i++) { 32.186 + if(strcmp(nodes[i]->get_name(), name) == 0) { 32.187 + return nodes[i]; 32.188 + } 32.189 + } 32.190 + return 0; 32.191 +} 32.192 + 32.193 +int Scene::get_node_count() const 32.194 +{ 32.195 + return (int)nodes.size(); 32.196 +} 32.197 + 32.198 + 32.199 +bool Scene::load(goat3d_io *io) 32.200 +{ 32.201 + return false; 32.202 +} 32.203 + 32.204 +// Scene::save is defined in goat3d_write.cc 32.205 + 32.206 + 32.207 +void io_fprintf(goat3d_io *io, const char *fmt, ...) 32.208 +{ 32.209 + va_list ap; 32.210 + 32.211 + va_start(ap, fmt); 32.212 + io_vfprintf(io, fmt, ap); 32.213 + va_end(ap); 32.214 +} 32.215 + 32.216 + 32.217 +void io_vfprintf(goat3d_io *io, const char *fmt, va_list ap) 32.218 +{ 32.219 + char smallbuf[256]; 32.220 + char *buf = smallbuf; 32.221 + int sz = sizeof smallbuf; 32.222 + 32.223 + int retsz = vsnprintf(buf, sz - 1, fmt, ap); 32.224 + 32.225 + if(retsz >= sz) { 32.226 + /* C99 mandates that snprintf with a short count should return the 32.227 + * number of characters that *would* be printed. 32.228 + */ 32.229 + buf = new char[retsz + 1]; 32.230 + 32.231 + vsnprintf(buf, retsz, fmt, ap); 32.232 + 32.233 + } else if(retsz <= 0) { 32.234 + /* SUSv2 and microsoft specify that snprintf with a short count 32.235 + * returns an arbitrary value <= 0. So let's try allocating 32.236 + * bigger and bigger arrays until we find the correct size. 32.237 + */ 32.238 + sz = sizeof smallbuf; 32.239 + do { 32.240 + sz *= 2; 32.241 + if(buf != smallbuf) { 32.242 + delete [] buf; 32.243 + } 32.244 + buf = new char[sz + 1]; 32.245 + 32.246 + retsz = vsnprintf(buf, sz, fmt, ap); 32.247 + } while(retsz <= 0); 32.248 + } 32.249 + 32.250 + io->write(buf, sz, io->cls); 32.251 + 32.252 + if(buf != smallbuf) { 32.253 + delete [] buf; 32.254 + } 32.255 + 32.256 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/src/goat3d_write.cc Thu Sep 26 04:47:05 2013 +0300 33.3 @@ -0,0 +1,220 @@ 33.4 +#include "goat3d_impl.h" 33.5 +#include "chunk.h" 33.6 + 33.7 +/* 33.8 +static long save_env(const Scene *scn, long offset, goat3d_io *io); 33.9 +static long save_materials(const Scene *scn, long offset, goat3d_io *io); 33.10 +static long save_material(const Material *mat, long offset, goat3d_io *io); 33.11 +static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io); 33.12 +static long save_meshes(const Scene *scn, long offset, goat3d_io *io); 33.13 +static long save_lights(const Scene *scn, long offset, goat3d_io *io); 33.14 +static long save_cameras(const Scene *scn, long offset, goat3d_io *io); 33.15 +static long save_nodes(const Scene *scn, long offset, goat3d_io *io); 33.16 + 33.17 +static long write_chunk_float(int id, float val, long offs, goat3d_io *io); 33.18 +static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io); 33.19 +static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io); 33.20 +*/ 33.21 + 33.22 +bool Scene::save(goat3d_io *io) const 33.23 +{ 33.24 + /* 33.25 + long res; 33.26 + 33.27 + ChunkHeader hdr; 33.28 + hdr.id = CNK_SCENE; 33.29 + hdr.size = sizeof hdr; 33.30 + 33.31 + if((res = save_env(this, hdr.size, io)) < 0) { 33.32 + return false; 33.33 + } 33.34 + hdr.size += res; 33.35 + 33.36 + if((res = save_materials(this, hdr.size, io)) < 0) { 33.37 + return false; 33.38 + } 33.39 + hdr.size += res; 33.40 + 33.41 + if((res = save_meshes(this, hdr.size, io)) < 0) { 33.42 + return false; 33.43 + } 33.44 + hdr.size += res; 33.45 + 33.46 + if((res = save_lights(this, hdr.size, io)) < 0) { 33.47 + return false; 33.48 + } 33.49 + hdr.size += res; 33.50 + 33.51 + if((res = save_cameras(this, hdr.size, io)) < 0) { 33.52 + return false; 33.53 + } 33.54 + hdr.size += res; 33.55 + 33.56 + if((res = save_nodes(this, hdr.size, io)) < 0) { 33.57 + return false; 33.58 + } 33.59 + hdr.size += res; 33.60 + 33.61 + // now go back and write the root chunk 33.62 + io->seek(0, SEEK_SET, io->cls); 33.63 + if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) { 33.64 + return false; 33.65 + } 33.66 + 33.67 + return true; 33.68 + */ 33.69 + return false; 33.70 +} 33.71 + 33.72 + 33.73 +#if 0 33.74 +static long save_env(const Scene *scn, long offset, goat3d_io *io) 33.75 +{ 33.76 + long res; 33.77 + 33.78 + ChunkHeader hdr; 33.79 + hdr.id = CNK_ENV; 33.80 + hdr.size = sizeof hdr; 33.81 + 33.82 + if((res = write_chunk_float3(CNK_ENV_AMBIENT, scn->get_ambient(), offset, io)) < 0) { 33.83 + return -1; 33.84 + } 33.85 + hdr.size += res; 33.86 + 33.87 + // TODO add fog chunk 33.88 + 33.89 + io->seek(offset, SEEK_SET, io->cls); 33.90 + if(io->write(&hdr, sizeof hdr, io->cls) < (ssize_t)sizeof hdr) { 33.91 + return -1; 33.92 + } 33.93 + return hdr.size; 33.94 +} 33.95 + 33.96 +static long save_materials(const Scene *scn, long offset, goat3d_io *io) 33.97 +{ 33.98 + long res; 33.99 + 33.100 + ChunkHeader hdr; 33.101 + hdr.id = CNK_MTL_LIST; 33.102 + hdr.size = sizeof hdr; 33.103 + 33.104 + for(int i=0; i<scn->get_material_count(); i++) { 33.105 + if((res = save_material(scn->get_material(i), offset + hdr.size, io)) < 0) { 33.106 + return -1; 33.107 + } 33.108 + hdr.size += res; 33.109 + } 33.110 + 33.111 + io->seek(offset, SEEK_SET, io->cls); 33.112 + if(io->write(&hdr, hdr.size, io->cls) < hdr.size) { 33.113 + return -1; 33.114 + } 33.115 + return hdr.size; 33.116 +} 33.117 + 33.118 +static long save_material(const Material *mat, long offset, goat3d_io *io) 33.119 +{ 33.120 + long res; 33.121 + 33.122 + ChunkHeader hdr; 33.123 + hdr.id = CNK_MTL; 33.124 + hdr.size = sizeof hdr; 33.125 + 33.126 + for(int i=0; i<mat->get_attrib_count(); i++) { 33.127 + const char *name = mat->get_attrib_name(i); 33.128 + if((res = save_mat_attrib(name, (*mat)[i], offset + hdr.size, io)) < 0) { 33.129 + return -1; 33.130 + } 33.131 + hdr.size += res; 33.132 + } 33.133 + 33.134 + io->seek(offset, SEEK_SET, io->cls); 33.135 + if(io->write(&hdr, hdr.size, io->cls) < hdr.size) { 33.136 + return -1; 33.137 + } 33.138 + return hdr.size; 33.139 +} 33.140 + 33.141 +static long save_mat_attrib(const char *name, const MaterialAttrib &attr, long offset, goat3d_io *io) 33.142 +{ 33.143 + long res; 33.144 + 33.145 + ChunkHeader hdr; 33.146 + hdr.id = CNK_MTL_ATTR; 33.147 + hdr.size = sizeof hdr; 33.148 + 33.149 + // TODO cont. 33.150 + return -1; 33.151 +} 33.152 + 33.153 +static long save_meshes(const Scene *scn, long offset, goat3d_io *io) 33.154 +{ 33.155 + return 0; 33.156 +} 33.157 + 33.158 +static long save_lights(const Scene *scn, long offset, goat3d_io *io) 33.159 +{ 33.160 + return 0; 33.161 +} 33.162 + 33.163 +static long save_cameras(const Scene *scn, long offset, goat3d_io *io) 33.164 +{ 33.165 + return 0; 33.166 +} 33.167 + 33.168 +static long save_nodes(const Scene *scn, long offset, goat3d_io *io) 33.169 +{ 33.170 + return 0; 33.171 +} 33.172 + 33.173 +static long write_chunk_float(int id, float val, long offs, goat3d_io *io) 33.174 +{ 33.175 + int size = sizeof(ChunkHeader) + sizeof val; 33.176 + char *buf = (char*)alloca(size); 33.177 + 33.178 + Chunk *c = (Chunk*)buf; 33.179 + c->hdr.id = id; 33.180 + c->hdr.size = size; 33.181 + *(float*)c->data = val; 33.182 + 33.183 + io->seek(offs, SEEK_SET, io->cls); 33.184 + if(io->write(buf, size, io->cls) < size) { 33.185 + return -1; 33.186 + } 33.187 + return size; 33.188 +} 33.189 + 33.190 +static long write_chunk_float3(int id, const Vector3 &vec, long offs, goat3d_io *io) 33.191 +{ 33.192 + int size = sizeof(ChunkHeader) + sizeof vec; 33.193 + char *buf = (char*)alloca(size); 33.194 + 33.195 + Chunk *c = (Chunk*)buf; 33.196 + c->hdr.id = id; 33.197 + c->hdr.size = size; 33.198 + *(Vector3*)c->data = vec; 33.199 + 33.200 + io->seek(offs, SEEK_SET, io->cls); 33.201 + if(io->write(buf, size, io->cls) < size) { 33.202 + return -1; 33.203 + } 33.204 + return size; 33.205 +} 33.206 + 33.207 +static long write_chunk_float4(int id, const Vector4 &vec, long offs, goat3d_io *io) 33.208 +{ 33.209 + int size = sizeof(ChunkHeader) + sizeof vec; 33.210 + char *buf = (char*)alloca(size); 33.211 + 33.212 + Chunk *c = (Chunk*)buf; 33.213 + c->hdr.id = id; 33.214 + c->hdr.size = size; 33.215 + *(Vector4*)c->data = vec; 33.216 + 33.217 + io->seek(offs, SEEK_SET, io->cls); 33.218 + if(io->write(buf, size, io->cls) < size) { 33.219 + return -1; 33.220 + } 33.221 + return size; 33.222 +} 33.223 +#endif
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/src/goat3d_writexml.cc Thu Sep 26 04:47:05 2013 +0300 34.3 @@ -0,0 +1,187 @@ 34.4 +#include <stdarg.h> 34.5 +#include "goat3d_impl.h" 34.6 +#include "chunk.h" 34.7 +#include "openctm.h" 34.8 + 34.9 +static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level); 34.10 +static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level); 34.11 +static void write_ctm_mesh(const Mesh *mesh, const char *fname); 34.12 +static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level); 34.13 +static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level); 34.14 +static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level); 34.15 +static void xmlout(goat3d_io *io, int level, const char *fmt, ...); 34.16 + 34.17 +bool Scene::savexml(goat3d_io *io) const 34.18 +{ 34.19 + xmlout(io, 0, "<scene>\n"); 34.20 + 34.21 + // write environment stuff 34.22 + xmlout(io, 1, "<env>\n"); 34.23 + xmlout(io, 1, "</env>\n"); 34.24 + 34.25 + for(size_t i=0; i<materials.size(); i++) { 34.26 + write_material(this, io, materials[i], 1); 34.27 + } 34.28 + for(size_t i=0; i<meshes.size(); i++) { 34.29 + write_mesh(this, io, meshes[i], i, 1); 34.30 + } 34.31 + for(size_t i=0; i<lights.size(); i++) { 34.32 + write_light(this, io, lights[i], 1); 34.33 + } 34.34 + for(size_t i=0; i<cameras.size(); i++) { 34.35 + write_camera(this, io, cameras[i], 1); 34.36 + } 34.37 + for(size_t i=0; i<nodes.size(); i++) { 34.38 + write_node(this, io, nodes[i], 1); 34.39 + } 34.40 + 34.41 + xmlout(io, 0, "</scene>\n"); 34.42 + return true; 34.43 +} 34.44 + 34.45 +static bool write_material(const Scene *scn, goat3d_io *io, const Material *mat, int level) 34.46 +{ 34.47 + xmlout(io, level, "<mtl>\n"); 34.48 + xmlout(io, level + 1, "<name string=\"%s\"/>\n", mat->name.c_str()); 34.49 + 34.50 + for(int i=0; i<mat->get_attrib_count(); i++) { 34.51 + xmlout(io, level + 1, "<attr>\n"); 34.52 + xmlout(io, level + 2, "<name string=\"%s\"/>\n", mat->get_attrib_name(i)); 34.53 + 34.54 + const MaterialAttrib &attr = (*mat)[i]; 34.55 + xmlout(io, level + 2, "<val float4=\"%.3f %.3f %.3f\"/>\n", attr.value.x, 34.56 + attr.value.y, attr.value.z, attr.value.w); 34.57 + if(!attr.map.empty()) { 34.58 + xmlout(io, level + 2, "<map string=\"%s\"/>\n", attr.map.c_str()); 34.59 + } 34.60 + xmlout(io, level + 1, "</attr>\n"); 34.61 + } 34.62 + xmlout(io, level, "</mtl>\n"); 34.63 + return true; 34.64 +} 34.65 + 34.66 +static bool write_mesh(const Scene *scn, goat3d_io *io, const Mesh *mesh, int idx, int level) 34.67 +{ 34.68 + // first write the external (openctm) mesh file 34.69 + const char *prefix = scn->get_name(); 34.70 + if(!prefix) { 34.71 + prefix = "goat"; 34.72 + } 34.73 + 34.74 + char *mesh_filename = (char*)alloca(strlen(prefix) + 32); 34.75 + sprintf(mesh_filename, "%s-mesh%04d.ctm", prefix, idx); 34.76 + 34.77 + write_ctm_mesh(mesh, mesh_filename); 34.78 + 34.79 + // then refer to that filename in the XML tags 34.80 + xmlout(io, level, "<mesh>\n"); 34.81 + xmlout(io, level + 1, "<name string=\"%s\"/>\n", mesh->name.c_str()); 34.82 + xmlout(io, level + 1, "<material string=\"%s\"/>\n", mesh->material->name.c_str()); 34.83 + xmlout(io, level + 1, "<file string=\"%s\"/>\n", mesh_filename); 34.84 + xmlout(io, level, "</mesh>\n"); 34.85 + return true; 34.86 +} 34.87 + 34.88 +static void write_ctm_mesh(const Mesh *mesh, const char *fname) 34.89 +{ 34.90 + int vnum = (int)mesh->vertices.size(); 34.91 + 34.92 + CTMcontext ctm = ctmNewContext(CTM_EXPORT); 34.93 + 34.94 + // vertices, normals, and face-vertex indices 34.95 + ctmDefineMesh(ctm, &mesh->vertices[0].x, vnum, (CTMuint*)mesh->faces[0].v, 34.96 + mesh->faces.size(), mesh->normals.empty() ? 0 : &mesh->normals[0].x); 34.97 + 34.98 + // texture coordinates 34.99 + if(!mesh->texcoords.empty()) { 34.100 + CTMfloat *uvarray = new CTMfloat[vnum * 2 * sizeof *uvarray]; 34.101 + CTMfloat *uvptr = uvarray; 34.102 + 34.103 + for(int i=0; i<vnum; i++) { 34.104 + *uvptr++ = mesh->texcoords[i].x; 34.105 + *uvptr++ = mesh->texcoords[i].y; 34.106 + } 34.107 + ctmAddUVMap(ctm, uvarray, "texcoord", 0); 34.108 + delete [] uvarray; 34.109 + } 34.110 + 34.111 + // vertex colors 34.112 + if(!mesh->colors.empty()) { 34.113 + ctmAddAttribMap(ctm, &mesh->colors[0].x, "color"); 34.114 + } 34.115 + 34.116 + // skin weights 34.117 + if(!mesh->skin_weights.empty()) { 34.118 + ctmAddAttribMap(ctm, &mesh->skin_weights[0].x, "skin_weight"); 34.119 + } 34.120 + 34.121 + // if either of the non-float4 attributes are present we need to make a tmp array 34.122 + CTMfloat *attr_array = 0; 34.123 + if(!mesh->tangents.empty() || !mesh->skin_matrices.empty()) { 34.124 + attr_array = new CTMfloat[vnum * 4 * sizeof *attr_array]; 34.125 + } 34.126 + 34.127 + // tangents 34.128 + if(!mesh->tangents.empty()) { 34.129 + CTMfloat *ptr = attr_array; 34.130 + 34.131 + for(int i=0; i<vnum; i++) { 34.132 + *ptr++ = mesh->tangents[i].x; 34.133 + *ptr++ = mesh->tangents[i].y; 34.134 + *ptr++ = mesh->tangents[i].z; 34.135 + *ptr++ = 1.0; 34.136 + } 34.137 + ctmAddAttribMap(ctm, attr_array, "tangent"); 34.138 + } 34.139 + 34.140 + // skin matrix indices (4 per vertex) 34.141 + if(!mesh->skin_matrices.empty()) { 34.142 + CTMfloat *ptr = attr_array; 34.143 + 34.144 + for(int i=0; i<vnum; i++) { 34.145 + *ptr++ = (float)mesh->skin_matrices[i].x; 34.146 + *ptr++ = (float)mesh->skin_matrices[i].y; 34.147 + *ptr++ = (float)mesh->skin_matrices[i].z; 34.148 + *ptr++ = (float)mesh->skin_matrices[i].w; 34.149 + } 34.150 + ctmAddAttribMap(ctm, attr_array, "skin_matrix"); 34.151 + } 34.152 + 34.153 + delete [] attr_array; 34.154 + 34.155 + /* TODO find a way to specify the nodes participating in the skinning of this mesh 34.156 + * probably in the comment field? 34.157 + */ 34.158 + 34.159 + ctmSave(ctm, fname); 34.160 + 34.161 + ctmFreeContext(ctm); 34.162 +} 34.163 + 34.164 +static bool write_light(const Scene *scn, goat3d_io *io, const Light *light, int level) 34.165 +{ 34.166 + return true; 34.167 +} 34.168 + 34.169 +static bool write_camera(const Scene *scn, goat3d_io *io, const Camera *cam, int level) 34.170 +{ 34.171 + return true; 34.172 +} 34.173 + 34.174 +static bool write_node(const Scene *scn, goat3d_io *io, const Node *node, int level) 34.175 +{ 34.176 + return true; 34.177 +} 34.178 + 34.179 + 34.180 +static void xmlout(goat3d_io *io, int level, const char *fmt, ...) 34.181 +{ 34.182 + for(int i=0; i<level; i++) { 34.183 + io_fprintf(io, " "); 34.184 + } 34.185 + 34.186 + va_list ap; 34.187 + va_start(ap, fmt); 34.188 + io_vfprintf(io, fmt, ap); 34.189 + va_end(ap); 34.190 +}